From e71dac0fe8ef80c7c39097d56117281decf17078 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 1 Feb 2016 15:17:48 -0200 Subject: [PATCH 001/234] Update changelog to 1.0.0-rc6 --- CHANGELOG.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 252682423..b3b084bcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,58 @@ # Change Log +## [v1.0.0-rc6](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc6) (2016-02-01) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc5...v1.0.0-rc6) + +**Implemented enhancements:** + +- CC0031 must not fire when Null-check is outside of a try block [\#672](https://github.com/code-cracker/code-cracker/issues/672) +- Add exceptions to CC0068 depending on the method attribute [\#526](https://github.com/code-cracker/code-cracker/issues/526) + +**Fixed bugs:** + +- BUG: CC0048 \(string interpolation\) when string is split into multiple lines [\#689](https://github.com/code-cracker/code-cracker/issues/689) +- CC0017 wrong change with explicitly implemented properties, but can be fixed [\#687](https://github.com/code-cracker/code-cracker/issues/687) +- CC0006 should be checking if for-looped array is enumerable by foreach [\#684](https://github.com/code-cracker/code-cracker/issues/684) +- BUG: CC0006 wrongly tries to convert for into foreach when there would be an assignment to the iteration variable [\#683](https://github.com/code-cracker/code-cracker/issues/683) +- CC0091 MakeMethodStaticCodeFixProvider crashing [\#682](https://github.com/code-cracker/code-cracker/issues/682) +- CC0091 wrongly tries to make static methods in structs [\#681](https://github.com/code-cracker/code-cracker/issues/681) +- BUG: CC0091 \(make static\) changes references incorrectly when used as a method group and in conjunction with another method invocation [\#680](https://github.com/code-cracker/code-cracker/issues/680) +- CC0091 on method Foo does not replace occurences like this.Foo used in delegates [\#677](https://github.com/code-cracker/code-cracker/issues/677) +- ObjectInitializerCodeFixProvider crashes [\#676](https://github.com/code-cracker/code-cracker/issues/676) +- Bug CC0084 should not generate string empty in parameter list in constructor or method [\#669](https://github.com/code-cracker/code-cracker/issues/669) +- CC0022 when theer is ternary operator in using [\#665](https://github.com/code-cracker/code-cracker/issues/665) +- CC0031 should not copy the variable with readonly members [\#663](https://github.com/code-cracker/code-cracker/issues/663) +- BUG on CC0047 \(PropertyPrivateSet\) suggests to make a property set private when the property is already private [\#658](https://github.com/code-cracker/code-cracker/issues/658) +- With more than one constructor, IntroduceFieldFromConstructorCodeFixProvider can replace wrong constructor [\#650](https://github.com/code-cracker/code-cracker/issues/650) +- BUG on CC0057 \(unused parameter\) with named parameters [\#649](https://github.com/code-cracker/code-cracker/issues/649) +- CC0057: Should not try to remove parameters meant to fulfill a delegate contract [\#646](https://github.com/code-cracker/code-cracker/issues/646) +- CC0016 should not copy the variable with readonly members [\#645](https://github.com/code-cracker/code-cracker/issues/645) +- BUG on CC0091 \(MakeMethodStatic\) when a reference to method is used as a method group [\#644](https://github.com/code-cracker/code-cracker/issues/644) +- BUG on CC0043 and CC0092 \(ChangeAnyToAll\) when invocation is negated [\#642](https://github.com/code-cracker/code-cracker/issues/642) +- BUG on CC0043 and CC0092 \(ChangeAnyToAll\) when invocation is in an expression bodied member [\#641](https://github.com/code-cracker/code-cracker/issues/641) +- AD0001 Crash [\#638](https://github.com/code-cracker/code-cracker/issues/638) +- BUG on CC0022 \(disposable not disposed\) fix when there is method chaining [\#630](https://github.com/code-cracker/code-cracker/issues/630) +- New word 'Foramt' in NameOfSymbolDisplayForamt [\#627](https://github.com/code-cracker/code-cracker/issues/627) +- CC0003 is shown even for catches which end with throw [\#626](https://github.com/code-cracker/code-cracker/issues/626) +- CC0001 is shown for variables with type dynamic and object [\#625](https://github.com/code-cracker/code-cracker/issues/625) +- CC0090 when using /// \ [\#624](https://github.com/code-cracker/code-cracker/issues/624) +- Bug: CC0017 not raised when using this [\#623](https://github.com/code-cracker/code-cracker/issues/623) +- CC0052 false positives [\#621](https://github.com/code-cracker/code-cracker/issues/621) +- Bug on CC0029 \(Call GC.SuppressFinalize on dispose\) with expression based methods [\#618](https://github.com/code-cracker/code-cracker/issues/618) +- Removing Option Parameter causes crash [\#617](https://github.com/code-cracker/code-cracker/issues/617) +- BUG on CC0043 and CC0092 \(ChangeAnyToAll\) when invocation has elvis operator [\#613](https://github.com/code-cracker/code-cracker/issues/613) +- When the dispose pattern is used do not raise CC0033 [\#603](https://github.com/code-cracker/code-cracker/issues/603) +- Suggested Nameof fix incorrectly suggests wrong type [\#594](https://github.com/code-cracker/code-cracker/issues/594) + ## [v1.0.0-rc5](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc5) (2015-12-03) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc4...v1.0.0-rc5) +**Implemented enhancements:** + +- CC0091 Know APIs [\#451](https://github.com/code-cracker/code-cracker/issues/451) +- Change CC0001 so that it does not apply to primitives [\#407](https://github.com/code-cracker/code-cracker/issues/407) +- Update all existing code fixes that are doing too much work on RegisterCodeFixesAsync \(VB\) [\#348](https://github.com/code-cracker/code-cracker/issues/348) + **Fixed bugs:** - BUG: UseInvokeMethodToFireEventAnalyzer throwing when method body is null [\#611](https://github.com/code-cracker/code-cracker/issues/611) @@ -22,11 +72,6 @@ - Bug with CC0009 when using the created object in the initialization [\#525](https://github.com/code-cracker/code-cracker/issues/525) - CC0013 Should check for a common type and cast is necessary. [\#521](https://github.com/code-cracker/code-cracker/issues/521) -**Implemented enhancements:** - -- Change CC0001 so that it does not apply to primitives [\#407](https://github.com/code-cracker/code-cracker/issues/407) -- Update all existing code fixes that are doing too much work on RegisterCodeFixesAsync \(VB\) [\#348](https://github.com/code-cracker/code-cracker/issues/348) - ## [v1.0.0-rc4](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc4) (2015-11-02) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc3...v1.0.0-rc4) From a553d66b5503066084438784fad2deacab91c966 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 1 Feb 2016 18:47:39 -0200 Subject: [PATCH 002/234] Update package names to solve error 500 This the error we were getting: Failed to process request. 'The title of your package, 'CodeCracker', is similar to the ID of an existing package, which can cause confusion with our users. Please modify the title of your package and try uploading again.'. The remote server returned an error: (500) Internal Server Error.. --- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CodeCracker.nuspec | 2 +- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index d248171e9..fb1a57fee 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -3,7 +3,7 @@ codecracker.CSharp 1.0.0-rc6 - CodeCracker + CodeCracker for C# giggio,elemarjr,carloscds giggio,elemarjr,carloscds https://github.com/code-cracker/code-cracker/blob/master/LICENSE.txt diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index 9de77c8de..e34681210 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -3,7 +3,7 @@ codecracker 1.0.0-rc6 - CodeCracker + CodeCracker for C# and VB giggio,elemarjr,carloscds giggio,elemarjr,carloscds https://github.com/code-cracker/code-cracker/blob/master/LICENSE.txt diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index 6571d3534..4245b4eeb 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -3,7 +3,7 @@ codecracker.VisualBasic 1.0.0-rc6 - CodeCracker + CodeCracker for Visual Basic giggio,elemarjr,carloscds giggio,elemarjr,carloscds https://github.com/code-cracker/code-cracker/blob/master/LICENSE.txt From bb585e29b90e5ca753f3d974a71722644a55ba63 Mon Sep 17 00:00:00 2001 From: carloscds Date: Mon, 1 Feb 2016 18:51:36 -0200 Subject: [PATCH 003/234] Fix #701 --- .../CodeCracker/Usage/UnusedParametersAnalyzer.cs | 2 +- .../Usage/RemoveUnusedVariablesTest.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs index 9f1071190..a0fdedc2f 100644 --- a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs @@ -122,7 +122,7 @@ private static bool IdentifierRefersToParam(IdentifierNameSyntax iName, Paramete private static bool IsCandidateForRemoval(BaseMethodDeclarationSyntax methodOrConstructor, SemanticModel semanticModel) { - if (methodOrConstructor.Modifiers.Any(m => m.ValueText == "partial" || m.ValueText == "override" || m.ValueText == "abstract") + if (methodOrConstructor.Modifiers.Any(m => m.ValueText == "partial" || m.ValueText == "override" || m.ValueText == "abstract" || m.ValueText == "extern") || !methodOrConstructor.ParameterList.Parameters.Any()) return false; var method = methodOrConstructor as MethodDeclarationSyntax; diff --git a/test/CSharp/CodeCracker.Test/Usage/RemoveUnusedVariablesTest.cs b/test/CSharp/CodeCracker.Test/Usage/RemoveUnusedVariablesTest.cs index 7d9c05d16..7732bb536 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RemoveUnusedVariablesTest.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RemoveUnusedVariablesTest.cs @@ -9,6 +9,20 @@ public class RemoveUnusedVariablesTest : CodeFixVerifier { protected override CodeFixProvider GetCodeFixProvider() => new RemoveUnusedVariablesCodeFixProvider(); + public async Task UsingExternNoDiagnostics() + { + const string source = @" + using System; + using System.Runtime.InteropServices; + + class TypeName + { + [DllImport(""wininet.dll"", SetLastError = true)] + public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int lpdwBufferLength); + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task WhenVariableIsAssignedButItsValueIsNeverUsedShouldCreateDiagnostics() { From 85fdf23f714e12f12f0e9786bb96407b70f95e73 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 29 Jan 2016 23:19:25 -0200 Subject: [PATCH 004/234] Fix nested interpolations Closes #690 --- src/CSharp/CodeCracker/CodeCracker.csproj | 1 + .../Style/ConsoleWriteLineCodeFixProvider.cs | 2 +- .../Style/StringFormatCodeFixProvider.cs | 17 +++-- .../Style/StringFormatFixAllProvider.cs | 67 +++++++++++++++++++ .../Style/StringFormatTests.cs | 30 +++++++++ 5 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index ebbcb04d4..3a914dbb4 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -81,6 +81,7 @@ + diff --git a/src/CSharp/CodeCracker/Style/ConsoleWriteLineCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/ConsoleWriteLineCodeFixProvider.cs index e84754466..a77edc2b5 100644 --- a/src/CSharp/CodeCracker/Style/ConsoleWriteLineCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/ConsoleWriteLineCodeFixProvider.cs @@ -31,7 +31,7 @@ private async static Task MakeStringInterpolationAsync(Document docume { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var invocationExpression = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - var newStringInterpolation = await StringFormatCodeFixProvider.CreateNewStringInterpolationAsync(document, invocationExpression, cancellationToken); + var newStringInterpolation = StringFormatCodeFixProvider.CreateNewStringInterpolation(invocationExpression); var newArgumentList = SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList().Add(SyntaxFactory.Argument(newStringInterpolation))); var newRoot = root.ReplaceNode(invocationExpression.ArgumentList, newArgumentList); var newDocument = document.WithSyntaxRoot(newRoot); diff --git a/src/CSharp/CodeCracker/Style/StringFormatCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/StringFormatCodeFixProvider.cs index 0c7df73b1..9772b3a3a 100644 --- a/src/CSharp/CodeCracker/Style/StringFormatCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/StringFormatCodeFixProvider.cs @@ -19,7 +19,7 @@ public class StringFormatCodeFixProvider : CodeFixProvider public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.StringFormat.ToDiagnosticId()); - public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + public sealed override FixAllProvider GetFixAllProvider() => StringFormatFixAllProvider.Instance; public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { @@ -32,16 +32,21 @@ private async static Task MakeStringInterpolationAsync(Document docume { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var invocationExpression = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - var newStringInterpolation = await CreateNewStringInterpolationAsync(document, invocationExpression, cancellationToken); - var newRoot = root.ReplaceNode(invocationExpression, newStringInterpolation); + var semanticModel = await document.GetSemanticModelAsync(cancellationToken); + var newRoot = CreateNewStringInterpolation(root, invocationExpression); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; } - public static async Task CreateNewStringInterpolationAsync(Document document, InvocationExpressionSyntax invocationExpression, CancellationToken cancellationToken) + public static SyntaxNode CreateNewStringInterpolation(SyntaxNode root, InvocationExpressionSyntax invocationExpression) + { + var newStringInterpolation = CreateNewStringInterpolation(invocationExpression); + var newRoot = root.ReplaceNode(invocationExpression, newStringInterpolation); + return newRoot; + } + + public static InterpolatedStringExpressionSyntax CreateNewStringInterpolation(InvocationExpressionSyntax invocationExpression) { - var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - var memberSymbol = semanticModel.GetSymbolInfo(invocationExpression.Expression).Symbol; var argumentList = invocationExpression.ArgumentList; var arguments = argumentList.Arguments; var formatLiteral = (LiteralExpressionSyntax)arguments[0].Expression; diff --git a/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs b/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs new file mode 100644 index 000000000..1c3416c81 --- /dev/null +++ b/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs @@ -0,0 +1,67 @@ +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Linq; +using System.Threading.Tasks; + +namespace CodeCracker.CSharp.Style +{ + public sealed class StringFormatFixAllProvider : FixAllProvider + { + private static readonly SyntaxAnnotation stringFormatAnnotation = new SyntaxAnnotation(nameof(StringFormatFixAllProvider)); + private StringFormatFixAllProvider() { } + public static readonly StringFormatFixAllProvider Instance = new StringFormatFixAllProvider(); + public override Task GetFixAsync(FixAllContext fixAllContext) + { + switch (fixAllContext.Scope) + { + case FixAllScope.Document: + return Task.FromResult(CodeAction.Create(Resources.StringFormatCodeFixProvider_Title, + async ct => fixAllContext.Document.WithSyntaxRoot(await GetFixedDocumentAsync(fixAllContext, fixAllContext.Document).ConfigureAwait(false)))); + case FixAllScope.Project: + return Task.FromResult(CodeAction.Create(Resources.StringFormatCodeFixProvider_Title, + ct => GetFixedProjectAsync(fixAllContext, fixAllContext.Project))); + case FixAllScope.Solution: + return Task.FromResult(CodeAction.Create(Resources.StringFormatCodeFixProvider_Title, + ct => GetFixedSolutionAsync(fixAllContext))); + } + return null; + } + + private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) + { + var newSolution = fixAllContext.Solution; + foreach (var projectId in newSolution.ProjectIds) + newSolution = await GetFixedProjectAsync(fixAllContext, newSolution.GetProject(projectId)).ConfigureAwait(false); + return newSolution; + } + + private async static Task GetFixedProjectAsync(FixAllContext fixAllContext, Project project) + { + var solution = project.Solution; + var newDocuments = project.Documents.ToDictionary(d => d.Id, d => GetFixedDocumentAsync(fixAllContext, d)); + await Task.WhenAll(newDocuments.Values).ConfigureAwait(false); + foreach (var newDoc in newDocuments) + solution = solution.WithDocumentSyntaxRoot(newDoc.Key, newDoc.Value.Result); + return solution; + } + + private async static Task GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) + { + var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); + var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); + var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan, getInnermostNodeForTie: true).FirstAncestorOrSelfOfType()).Where(n => !n.IsMissing).ToList(); + var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => rewritten.WithAdditionalAnnotations(stringFormatAnnotation)); + while (true) + { + var annotatedNodes = newRoot.GetAnnotatedNodes(stringFormatAnnotation); + var node = annotatedNodes.FirstOrDefault(); + if (node == null) break; + newRoot = StringFormatCodeFixProvider.CreateNewStringInterpolation(newRoot, (InvocationExpressionSyntax)node); + } + return newRoot; + } + } +} \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs b/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs index b1e31397d..76ccf4a94 100644 --- a/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs @@ -636,5 +636,35 @@ public async Task FixWithLineBreaksAndStringConcat() var baz = $""{foo + ""baz"" + ""boo""}"";".WrapInCSharpMethod(); await VerifyCSharpFixAsync(source, expected); } + + [Fact] + public async Task NestedStringFormatCreatesDiagnostic() + { + var source = @"var foo = string.Format(""{0}"", string.Format(""{0}"", 1 ) );".WrapInCSharpMethod(); + var expected1 = new DiagnosticResult + { + Id = DiagnosticId.StringFormat.ToDiagnosticId(), + Message = StringFormatAnalyzer.MessageFormat.ToString(), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 27) } + }; + var expected2 = new DiagnosticResult + { + Id = DiagnosticId.StringFormat.ToDiagnosticId(), + Message = StringFormatAnalyzer.MessageFormat.ToString(), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 48) } + }; + await VerifyCSharpDiagnosticAsync(source, expected1, expected2); + } + + [Fact] + public async Task FixAllStringInterpolations() + { +var foo = $"{$"{1}"}"; + var source = @"var foo = string.Format(""{0}"", string.Format(""{0}"", 1 ) );".WrapInCSharpMethod(); + var expected = @"var foo = $""{$""{1}""}"";".WrapInCSharpMethod(); + await VerifyCSharpFixAllAsync(source, expected); + } } } \ No newline at end of file From 21208c047cedab28a05d98d22982f7b2e6cf6b3b Mon Sep 17 00:00:00 2001 From: Vossekop Date: Tue, 2 Feb 2016 21:39:45 +0100 Subject: [PATCH 005/234] GetEnumerator method returning an IEnumerator is now ignored in CC00091 --- .../Design/MakeMethodStaticAnalyzer.cs | 8 +++- .../Design/MakeMethodStaticTests.cs | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs b/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs index eb128c92a..d8dc98556 100644 --- a/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs @@ -79,12 +79,13 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) if (IsTestMethod(method, methodSymbol)) return; if (IsWebFormsMethod(methodSymbol)) return; + if (IsGetEnumerator(methodSymbol)) return; var diagnostic = Diagnostic.Create(Rule, method.Identifier.GetLocation(), method.Identifier.ValueText); context.ReportDiagnostic(diagnostic); } - private static readonly string[] webFormsMethods = new string[] { + private static readonly string[] webFormsMethods = { "Application_AuthenticateRequest", "Application_BeginRequest", "Application_End", "Application_EndRequest", "Application_Error", "Application_Start", @@ -95,6 +96,11 @@ private static bool IsWebFormsMethod(IMethodSymbol methodSymbol) return (methodSymbol.ContainingType.AllBaseTypes().Any(t => t.ToString() == "System.Web.HttpApplication")); } + private static bool IsGetEnumerator(IMethodSymbol methodSymbol) + { + return methodSymbol.Name == "GetEnumerator" && methodSymbol.ReturnType.Name == "IEnumerator"; + } + private static bool IsTestMethod(MethodDeclarationSyntax method, IMethodSymbol methodSymbol) { var result = false; diff --git a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs index cc980214d..cafcd4950 100644 --- a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs @@ -1023,5 +1023,44 @@ public static void N() { } }; await VerifyCSharpDiagnosticAsync(source, expected); } + + [Fact] + public async Task IgnoreForGetEnumerator() + { + const string source = @" +class Foo +{ + public System.Collections.IEnumerator GetEnumerator() + { + yield return 1; + yield return 2; + } +}"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task ReportForGetEnumeratorNotReturningIEnumerator() + { + const string source = @" +class Foo +{ + public void GetEnumerator() + { + N(); + } + + public static void N() { } +}"; + var expected = new DiagnosticResult + { + Id = DiagnosticId.MakeMethodStatic.ToDiagnosticId(), + Message = string.Format(MakeMethodStaticAnalyzer.MessageFormat, "GetEnumerator"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 17) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } } } \ No newline at end of file From 33b02e080146da34001b160a4aaa7b659c2d3103 Mon Sep 17 00:00:00 2001 From: "coolrunr@drautage.com" Date: Sat, 6 Feb 2016 18:44:20 -0600 Subject: [PATCH 006/234] Test accessibility when determining if field can be read only. --- .../Usage/ReadonlyFieldAnalyzer.cs | 9 +++++ .../Usage/ReadonlyFieldTests.cs | 34 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index cf4e39b76..97d3ebd64 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -96,6 +96,7 @@ private static void VerifyVariable(Dictionary GetTypesInRoot(SyntaxNode root) { var types = new List(); diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index ec7e2aaf8..b7fb708b6 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -804,10 +804,10 @@ public void Foo() await VerifyCSharpHasNoDiagnosticsAsync(source1, source2); } - [Fact] - public async Task FieldsAssignedOnLambdaDoesNotCreateDiagnostic() - { - const string source = @" + [Fact] + public async Task FieldsAssignedOnLambdaDoesNotCreateDiagnostic() + { + const string source = @" namespace ConsoleApplication1 { internal class Test @@ -820,7 +820,31 @@ public Test() } } }"; - await VerifyCSharpHasNoDiagnosticsAsync(source); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task VariableInitializerDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + class A + { + public int X; + + public A() + { + X = 5; + } + } + + static void B() + { + var c = new A { X = 7 }; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); } } } From 96249db8506eb9c60a1b2cece7c6598bcbbab05e Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 8 Feb 2016 17:39:50 -0200 Subject: [PATCH 007/234] Keep existing modifiers when making an autoprop Closes #699 --- .../Style/SwitchToAutoPropAnalyzer.cs | 6 +- .../Style/SwitchToAutoPropCodeFixProvider.cs | 70 +++++++++++++------ .../Style/SwitchToAutoPropTests.cs | 28 ++++++++ 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/SwitchToAutoPropAnalyzer.cs b/src/CSharp/CodeCracker/Style/SwitchToAutoPropAnalyzer.cs index 87dd2f577..a51c2dff6 100644 --- a/src/CSharp/CodeCracker/Style/SwitchToAutoPropAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/SwitchToAutoPropAnalyzer.cs @@ -56,13 +56,13 @@ private static void AnalyzeProperty(SyntaxNodeAnalysisContext context, bool canH ((MemberAccessExpressionSyntax)getterReturn.Expression).Expression is ThisExpressionSyntax ? ((MemberAccessExpressionSyntax)getterReturn.Expression).Name : getterReturn.Expression) as IdentifierNameSyntax; if (returnIdentifier == null) return; var semanticModel = context.SemanticModel; - var returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; - if (returnIdentifierSymbol == null) return; + var fieldSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; + if (fieldSymbol == null) return; var assignmentLeftIdentifier = (setterAssignmentExpression.Left is MemberAccessExpressionSyntax && ((MemberAccessExpressionSyntax)setterAssignmentExpression.Left).Expression is ThisExpressionSyntax ? ((MemberAccessExpressionSyntax)setterAssignmentExpression.Left).Name : setterAssignmentExpression.Left) as IdentifierNameSyntax; if (assignmentLeftIdentifier == null) return; var assignmentLeftIdentifierSymbol = semanticModel.GetSymbolInfo(assignmentLeftIdentifier).Symbol; - if (!assignmentLeftIdentifierSymbol.Equals(returnIdentifierSymbol)) return; + if (!assignmentLeftIdentifierSymbol.Equals(fieldSymbol)) return; var assignmentRightIdentifier = setterAssignmentExpression.Right as IdentifierNameSyntax; if (assignmentRightIdentifier == null) return; if (assignmentRightIdentifier.Identifier.Text != "value") return; diff --git a/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs index 093b9e7de..025187f54 100644 --- a/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs @@ -42,47 +42,41 @@ public async static Task MakeAutoPropertyAsync(Document document, Synt { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var getterReturn = (ReturnStatementSyntax)property.AccessorList.Accessors.First(a => a.Keyword.ValueText == "get").Body.Statements.First(); - var returnIdentifier = (IdentifierNameSyntax)(getterReturn.Expression is MemberAccessExpressionSyntax ? ((MemberAccessExpressionSyntax)getterReturn.Expression).Name : getterReturn.Expression); - var returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; - var variableDeclarator = (VariableDeclaratorSyntax)returnIdentifierSymbol.DeclaringSyntaxReferences.First().GetSyntax(); + var returnIdentifier = (IdentifierNameSyntax)(getterReturn.Expression is MemberAccessExpressionSyntax + ? ((MemberAccessExpressionSyntax)getterReturn.Expression).Name + : getterReturn.Expression); + var fieldSymbol = (IFieldSymbol)semanticModel.GetSymbolInfo(returnIdentifier).Symbol; + var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.DeclaringSyntaxReferences.First().GetSyntax(); var fieldDeclaration = variableDeclarator.FirstAncestorOfType(); - var fieldSymbol = (IFieldSymbol)semanticModel.GetDeclaredSymbol(variableDeclarator); var propertySymbol = semanticModel.GetDeclaredSymbol(property); root = root.TrackNodes(returnIdentifier, fieldDeclaration, property); document = document.WithSyntaxRoot(root); root = await document.GetSyntaxRootAsync(cancellationToken); semanticModel = await document.GetSemanticModelAsync(cancellationToken); returnIdentifier = root.GetCurrentNode(returnIdentifier); - returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; - var newProperty = GetSimpleProperty(property, variableDeclarator); + fieldSymbol = (IFieldSymbol)semanticModel.GetSymbolInfo(returnIdentifier).Symbol; + var newProperty = CreateAutoProperty(property, variableDeclarator, fieldSymbol, propertySymbol); Solution newSolution; - if (!propertySymbol.ExplicitInterfaceImplementations.Any()) + if (IsExplicityImplementation(propertySymbol)) { - newProperty = newProperty.WithModifiers(propertySymbol.DeclaredAccessibility - .GetMinimumCommonAccessibility(fieldSymbol.DeclaredAccessibility) - .GetTokens()); - newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, returnIdentifierSymbol, property.Identifier.ValueText, document.Project.Solution.Workspace.Options, cancellationToken).ConfigureAwait(false); + newSolution = await RenameSymbolAndKeepExplicitPropertiesBoundAsync(document.Project.Solution, property.Identifier.ValueText, fieldSymbol, propertySymbol, cancellationToken); } else { - newSolution = await RenameSymbolAndKeepExplicitPropertiesBoundAsync(document.Project.Solution, property.Identifier.ValueText, returnIdentifierSymbol, propertySymbol, cancellationToken); + newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, fieldSymbol, property.Identifier.ValueText, document.Project.Solution.Workspace.Options, cancellationToken).ConfigureAwait(false); } - newProperty = newProperty - .WithTriviaFrom(property) - .WithAdditionalAnnotations(Formatter.Annotation); document = newSolution.GetDocument(document.Id); root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - root = root.InsertNodesAfter(root.GetCurrentNode(property), new[] { newProperty }); + root = root.ReplaceNode(root.GetCurrentNode(property), newProperty); var multipleVariableDeclaration = fieldDeclaration.Declaration.Variables.Count > 1; if (multipleVariableDeclaration) { var newfieldDeclaration = fieldDeclaration.WithDeclaration(fieldDeclaration.Declaration.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepNoTrivia)); - root = root.RemoveNode(root.GetCurrentNode(property), SyntaxRemoveOptions.KeepNoTrivia); root = root.ReplaceNode(root.GetCurrentNode(fieldDeclaration), newfieldDeclaration); } else { - root = root.RemoveNodes(root.GetCurrentNodes(new SyntaxNode[] { fieldDeclaration, property }), SyntaxRemoveOptions.KeepNoTrivia); + root = root.RemoveNode(root.GetCurrentNode(fieldDeclaration), SyntaxRemoveOptions.KeepNoTrivia); } document = document.WithSyntaxRoot(root); return document.Project.Solution; @@ -132,16 +126,46 @@ private static async Task RenameSymbolAndKeepExplicitPropertiesBoundAs return newSolution; } - private static PropertyDeclarationSyntax GetSimpleProperty(PropertyDeclarationSyntax property, VariableDeclaratorSyntax variableDeclarator) + private static PropertyDeclarationSyntax CreateAutoProperty(PropertyDeclarationSyntax property, VariableDeclaratorSyntax variableDeclarator, + IFieldSymbol fieldSymbol, IPropertySymbol propertySymbol) { - var simpleGetSetPropetie = property.WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { + var newProperty = property.WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)), SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) }))); - return variableDeclarator.Initializer == null ? - simpleGetSetPropetie : - simpleGetSetPropetie.WithInitializer(variableDeclarator.Initializer) + newProperty = variableDeclarator.Initializer == null ? + newProperty : + newProperty.WithInitializer(variableDeclarator.Initializer) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + newProperty = CreatePropertyWithCorrectAccessibility(newProperty, fieldSymbol, propertySymbol); + newProperty = newProperty + .WithTriviaFrom(property) + .WithAdditionalAnnotations(Formatter.Annotation); + return newProperty; } + + private static PropertyDeclarationSyntax CreatePropertyWithCorrectAccessibility(PropertyDeclarationSyntax property, IFieldSymbol fieldSymbol, IPropertySymbol propertySymbol) + { + if (IsExplicityImplementation(propertySymbol)) + return property; + var existingModifiers = property.Modifiers.Where(m => + { + var modifierText = m.ValueText; + return modifierText != "private" + && modifierText != "protected" + && modifierText != "public" + && modifierText != "internal"; + }); + var newAccessibilityModifiers = propertySymbol.DeclaredAccessibility + .GetMinimumCommonAccessibility(fieldSymbol.DeclaredAccessibility) + .GetTokens() + .Aggregate(existingModifiers, (ts, t) => + ts.Any(tt => tt.ValueText == t.ValueText) ? ts : ts.Union(new[] { t }).ToArray()) + .OrderBy(t => t.ValueText); + var newProperty = property.WithModifiers(SyntaxFactory.TokenList(newAccessibilityModifiers)); + return newProperty; + } + + private static bool IsExplicityImplementation(IPropertySymbol propertySymbol) => propertySymbol.ExplicitInterfaceImplementations.Any(); } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs b/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs index da9886e5b..e1417913f 100644 --- a/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs @@ -873,5 +873,33 @@ static void Baz() }"; await VerifyCSharpFixAllAsync(new[] { source1, source2 }, new[] { expected1, expected2 }); } + + [Fact] + public async Task FixKeepsStaticModifier() + { + const string source = @" + private int y; + public virtual int Y + { + get { return y; } + set { y = value; } + }"; + const string expected = @"public virtual int Y { get; set; }"; + await VerifyCSharpFixAsync(source.WrapInCSharpClass(), expected.WrapInCSharpClass()); + } + + [Fact] + public async Task FixKeepsVirtualModifier() + { + const string source = @" + private static int y; + public static int Y + { + get { return y; } + set { y = value; } + }"; + const string expected = @"public static int Y { get; set; }"; + await VerifyCSharpFixAsync(source.WrapInCSharpClass(), expected.WrapInCSharpClass()); + } } } \ No newline at end of file From 9128acd4e60ef0451f141ddc0fd58db5fff8cbf6 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 8 Feb 2016 18:39:52 -0200 Subject: [PATCH 008/234] Fix switch to autoprop with self references Closes #702 --- .../Style/SwitchToAutoPropCodeFixProvider.cs | 90 ++++++++++++++----- .../Style/SwitchToAutoPropTests.cs | 35 ++++++++ 2 files changed, 102 insertions(+), 23 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs index 025187f54..b5a2bdfd6 100644 --- a/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixProvider.cs @@ -49,40 +49,68 @@ public async static Task MakeAutoPropertyAsync(Document document, Synt var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.DeclaringSyntaxReferences.First().GetSyntax(); var fieldDeclaration = variableDeclarator.FirstAncestorOfType(); var propertySymbol = semanticModel.GetDeclaredSymbol(property); - root = root.TrackNodes(returnIdentifier, fieldDeclaration, property); - document = document.WithSyntaxRoot(root); - root = await document.GetSyntaxRootAsync(cancellationToken); - semanticModel = await document.GetSemanticModelAsync(cancellationToken); - returnIdentifier = root.GetCurrentNode(returnIdentifier); - fieldSymbol = (IFieldSymbol)semanticModel.GetSymbolInfo(returnIdentifier).Symbol; + var newRoot = root.TrackNodes(returnIdentifier, fieldDeclaration, property, variableDeclarator); + //cycle + var newDocument = document.WithSyntaxRoot(newRoot); + newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken); var newProperty = CreateAutoProperty(property, variableDeclarator, fieldSymbol, propertySymbol); Solution newSolution; if (IsExplicityImplementation(propertySymbol)) { - newSolution = await RenameSymbolAndKeepExplicitPropertiesBoundAsync(document.Project.Solution, property.Identifier.ValueText, fieldSymbol, propertySymbol, cancellationToken); + semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken); + returnIdentifier = newRoot.GetCurrentNode(returnIdentifier); + fieldSymbol = (IFieldSymbol)semanticModel.GetSymbolInfo(returnIdentifier).Symbol; + newSolution = await RenameSymbolAndKeepExplicitPropertiesBoundAsync(newDocument.Project.Solution, property.Identifier.ValueText, fieldSymbol, propertySymbol, cancellationToken); + newDocument = newSolution.GetDocument(newDocument.Id); + newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(property), newProperty); + newSolution = newSolution.WithDocumentSyntaxRoot(newDocument.Id, newRoot); } else { - newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, fieldSymbol, property.Identifier.ValueText, document.Project.Solution.Workspace.Options, cancellationToken).ConfigureAwait(false); + var currentProperty = newRoot.GetCurrentNode(property); + var type = (TypeDeclarationSyntax)currentProperty.Parent; + var propertyIndex = type.Members.IndexOf(currentProperty); + //Remove the property: this is needed otherwise the rename that happens bellow will not be able to + //correctly redirect the references to the field, as the property will conflict with the name. + //The conflict is specially troublesome for circular references, such as the one that caused the bug #702. + newRoot = newRoot.ReplaceNode(type, type.RemoveNode(currentProperty, SyntaxRemoveOptions.KeepNoTrivia)); + //cycle + newDocument = newDocument.WithSyntaxRoot(newRoot); + newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken); + semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken); + fieldSymbol = (IFieldSymbol)semanticModel.GetDeclaredSymbol(newRoot.GetCurrentNode(variableDeclarator)); + //rename the field: + newSolution = await Renamer.RenameSymbolAsync(newDocument.Project.Solution, fieldSymbol, property.Identifier.ValueText, newDocument.Project.Solution.Workspace.Options, cancellationToken).ConfigureAwait(false); + //cycle + newDocument = newSolution.GetDocument(newDocument.Id); + newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + //add the property back: + var currentType = (TypeDeclarationSyntax)newRoot.GetCurrentNode(fieldDeclaration).Parent; + var newMembers = currentType.Members.Insert(propertyIndex, newProperty); + var newType = WithMembers(currentType, newMembers); + newRoot = newRoot.ReplaceNode(currentType, newType); + newSolution = newSolution.WithDocumentSyntaxRoot(newDocument.Id, newRoot); } - document = newSolution.GetDocument(document.Id); - root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - root = root.ReplaceNode(root.GetCurrentNode(property), newProperty); + newDocument = newSolution.GetDocument(newDocument.Id); + newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + newRoot = RemoveField(newRoot, variableDeclarator, fieldDeclaration); + return newSolution.WithDocumentSyntaxRoot(newDocument.Id, newRoot); + } + + private static SyntaxNode RemoveField(SyntaxNode root, VariableDeclaratorSyntax variableDeclarator, FieldDeclarationSyntax fieldDeclaration) + { + var currentField = root.GetCurrentNode(fieldDeclaration); var multipleVariableDeclaration = fieldDeclaration.Declaration.Variables.Count > 1; - if (multipleVariableDeclaration) - { - var newfieldDeclaration = fieldDeclaration.WithDeclaration(fieldDeclaration.Declaration.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepNoTrivia)); - root = root.ReplaceNode(root.GetCurrentNode(fieldDeclaration), newfieldDeclaration); - } - else - { - root = root.RemoveNode(root.GetCurrentNode(fieldDeclaration), SyntaxRemoveOptions.KeepNoTrivia); - } - document = document.WithSyntaxRoot(root); - return document.Project.Solution; + root = multipleVariableDeclaration + ? root.ReplaceNode(currentField, fieldDeclaration + .WithDeclaration(fieldDeclaration.Declaration.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepNoTrivia))) + : root.RemoveNode(currentField, SyntaxRemoveOptions.KeepNoTrivia); + return root; } - private static async Task RenameSymbolAndKeepExplicitPropertiesBoundAsync(Solution solution, string propertyName, ISymbol returnIdentifierSymbol, IPropertySymbol propertySymbol, CancellationToken cancellationToken) + private static async Task RenameSymbolAndKeepExplicitPropertiesBoundAsync(Solution solution, string propertyName, + ISymbol returnIdentifierSymbol, IPropertySymbol propertySymbol, CancellationToken cancellationToken) { var interfaceType = propertySymbol.ExplicitInterfaceImplementations.First().ContainingType; var references = await SymbolFinder.FindReferencesAsync(returnIdentifierSymbol, solution, cancellationToken).ConfigureAwait(false); @@ -167,5 +195,21 @@ private static PropertyDeclarationSyntax CreatePropertyWithCorrectAccessibility( } private static bool IsExplicityImplementation(IPropertySymbol propertySymbol) => propertySymbol.ExplicitInterfaceImplementations.Any(); + + private static TypeDeclarationSyntax WithMembers(TypeDeclarationSyntax type, SyntaxList newMembers) + { + TypeDeclarationSyntax newType; + var classDeclaration = type as ClassDeclarationSyntax; + if (classDeclaration != null) + { + newType = classDeclaration.WithMembers(newMembers); + } + else + { + var structDeclaration = (StructDeclarationSyntax)type; + newType = structDeclaration.WithMembers(newMembers); + } + return newType; + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs b/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs index e1417913f..157d86c37 100644 --- a/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/SwitchToAutoPropTests.cs @@ -901,5 +901,40 @@ public static int Y const string expected = @"public static int Y { get; set; }"; await VerifyCSharpFixAsync(source.WrapInCSharpClass(), expected.WrapInCSharpClass()); } + + [Fact] + public async Task FixUpdatesDerivedClassesCorrectly() + { + const string source = @" +class Point +{ + protected int x; + public virtual int X + { + get + { + return x; + } + set + { + x = value; + } + } +} +class NewPoint : Point +{ + public override int X => (x - 15); +}"; + const string expected = @" +class Point +{ + public virtual int X { get; set; } +} +class NewPoint : Point +{ + public override int X => (base.X - 15); +}"; + await VerifyCSharpFixAsync(source, expected); + } } } \ No newline at end of file From 16d58ee379185986d9e59e4f143716e740e19b40 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 8 Feb 2016 19:46:05 -0200 Subject: [PATCH 009/234] Fix DisposableFieldNotDisposedAnalyzer to ignore static fields Closes #710 --- .../Usage/DisposableFieldNotDisposedAnalyzer.cs | 1 + .../Usage/DisposableFieldNotDisposedTests.cs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs index 3632de804..e38d7959d 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs @@ -43,6 +43,7 @@ private static void AnalyzeField(SymbolAnalysisContext context) { if (context.IsGenerated()) return; var fieldSymbol = (IFieldSymbol)context.Symbol; + if (fieldSymbol.IsStatic) return; if (!fieldSymbol.Type.AllInterfaces.Any(i => i.ToString() == "System.IDisposable") && fieldSymbol.Type.ToString() != "System.IDisposable") return; var fieldSyntaxRef = fieldSymbol.DeclaringSyntaxReferences.FirstOrDefault(); var variableDeclarator = fieldSyntaxRef.GetSyntax() as VariableDeclaratorSyntax; diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs index b66e1f327..123a05cb5 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs @@ -772,6 +772,21 @@ class TypeName : System.IDisposable public void Dispose() => field.Dispose(); } class D : System.IDisposable +{ + public void Dispose() { } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task StaticFieldDoesNotCreateDiagnostic() + { + const string source = @" +static class TypeName +{ + private static D d = new D(); +} +class D : System.IDisposable { public void Dispose() { } }"; From 05cab438e6a1079fcbf2f1512ea17067b59d0599 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 8 Feb 2016 20:15:22 -0200 Subject: [PATCH 010/234] Fixes VirtualMethodOnConstructorAnalyzer to check params Closes #712 Also fixes tests that had incorrect {{ or }}. --- .../VirtualMethodOnConstructorAnalyzer.cs | 20 ++-- .../Usage/VirtualMethodOnConstructorTests.cs | 94 ++++++++++--------- 2 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/VirtualMethodOnConstructorAnalyzer.cs b/src/CSharp/CodeCracker/Usage/VirtualMethodOnConstructorAnalyzer.cs index ce6cfa2eb..f0d2becef 100644 --- a/src/CSharp/CodeCracker/Usage/VirtualMethodOnConstructorAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/VirtualMethodOnConstructorAnalyzer.cs @@ -40,13 +40,21 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var ctor = (ConstructorDeclarationSyntax)context.Node; if (ctor.Body == null) return; var methodInvocations = ctor.Body.DescendantNodes().OfType(); - foreach (var method in methodInvocations) + var semanticModel = context.SemanticModel; + foreach (var invocation in methodInvocations) { - var identifier = method.Expression as IdentifierNameSyntax; - if (identifier == null && !method.ToString().StartsWith("this")) return; - var methodDeclaration = context.SemanticModel.GetSymbolInfo(method).Symbol; - if (methodDeclaration == null || !methodDeclaration.IsVirtual) return; - var diagnostic = Diagnostic.Create(Rule, method.GetLocation()); + var identifier = invocation.Expression as IdentifierNameSyntax; + if (identifier == null) + { + if (!invocation.ToString().StartsWith("this.")) return; + } + else + { + if (semanticModel.GetSymbolInfo(identifier).Symbol is IParameterSymbol) return; + } + var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol; + if (methodSymbol == null || !methodSymbol.IsVirtual) return; + var diagnostic = Diagnostic.Create(Rule, invocation.GetLocation()); context.ReportDiagnostic(diagnostic); } } diff --git a/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs b/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs index fd76931c3..eb2775560 100644 --- a/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs @@ -11,16 +11,16 @@ public class VirtualMethodOnConstructorTests : DiagnosticVerifier { public async Task IfVirtualMethodFoundInConstructorCreatesDiagnostic() { const string test = @" public class Person -{{ +{ public Person(string foo) - {{ + { DoFoo(foo); - }} + } public virtual void DoFoo(string foo) - {{ - }} -}}"; + { + } +}"; var expected = new DiagnosticResult { Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), Message = VirtualMethodOnConstructorAnalyzer.Message, @@ -35,16 +35,16 @@ public virtual void DoFoo(string foo) public async Task IfVirtualMethodWithThisFoundInConstructorCreatesDiagnostic() { const string test = @" public class Person -{{ +{ public Person(string foo) - {{ + { this.DoFoo(foo); - }} + } public virtual void DoFoo(string foo) - {{ - }} -}}"; + { + } +}"; var expected = new DiagnosticResult { Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), Message = VirtualMethodOnConstructorAnalyzer.Message, @@ -60,20 +60,19 @@ public virtual void DoFoo(string foo) public async Task IfVirtualMethodFoundFromOtherClassInConstructorDoNotCreateDiagnostic() { const string test = @" public class Book -{{ +{ public virtual void DoFoo(string foo) - {{ - }} -}} + { + } +} public class Person -{{ +{ public Person(string foo) - {{ + { var b = new Book(); b.DoFoo(foo); - }} -}} -"; + } +}"; await VerifyCSharpHasNoDiagnosticsAsync(test); } @@ -81,16 +80,15 @@ public Person(string foo) public async Task IfVirtualMethodNotFoundInConstructorDoNotCreateDiagnostic() { const string test = @" public class Person -{{ +{ public Person(string foo) - {{ + { DoFoo(foo); - }} - + } public void DoFoo(string foo) - {{ - }} -}}"; + { + } +}"; await VerifyCSharpHasNoDiagnosticsAsync(test); } @@ -98,20 +96,20 @@ public void DoFoo(string foo) public async Task IfManyVirtualMethodFoundInConstructorCreatesDiagnostics() { const string test = @" public class Person -{{ +{ public Person(string foo) - {{ + { DoFoo(foo); DoFoo2(foo); - }} + } public virtual void DoFoo(string foo) - {{ - }} + { + } public virtual void DoFoo2(string foo) - {{ - }} -}}"; + { + } +}"; var expected = new DiagnosticResult { Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), Message = VirtualMethodOnConstructorAnalyzer.Message, @@ -124,8 +122,6 @@ public virtual void DoFoo2(string foo) Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 3) } }; - - await VerifyCSharpDiagnosticAsync(test, expected, expected2); } @@ -137,12 +133,26 @@ protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() { public async Task IfNameOfFoundInConstructorDoesNotCreateDiagnostic() { const string test = @" public class Person -{{ +{ public Person(string name) - {{ + { throw new System.ArgumentOutOfRangeException(nameof(name), """"); - }} -}}"; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] + public async Task IgnoreParameters() { + var test = @" +using System; +class Foo +{ + public Foo(Func bar) + { + bar(); + } +}"; await VerifyCSharpHasNoDiagnosticsAsync(test); } } From 174cecb2c703394dad38639643de10b35058d837 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Wed, 17 Feb 2016 16:26:28 -0200 Subject: [PATCH 011/234] Fix object initializer fix to not delete statements Fixes #717 --- .../Style/ObjectInitializerCodeFixProvider.cs | 2 +- .../Style/ObjectInitializerTests.cs | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Style/ObjectInitializerCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/ObjectInitializerCodeFixProvider.cs index 11da2a447..258d8975a 100644 --- a/src/CSharp/CodeCracker/Style/ObjectInitializerCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/ObjectInitializerCodeFixProvider.cs @@ -131,7 +131,7 @@ private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, Seman .WithTrailingTrivia(statement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement); - i += initializationExpressions.Count; + i += assignmentExpressions.Count; } else { diff --git a/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs b/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs index 98f66c406..b4e1b5ddb 100644 --- a/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs @@ -183,6 +183,50 @@ public int Foo() await VerifyCSharpFixAsync(source, fixtest, 0); } + [Fact] + public async Task FixDoesNotRemoveNextStatement() + { + const string source = @" +class DataObject +{ + public int MyInt { get; set; } + public double MyDouble { get; set; } +} + +class Program +{ + static void Main() + { + var data = new DataObject + { + MyInt = 5 + }; + data.MyDouble = 5.6; + var a = 1; + } +}"; + const string fixtest = @" +class DataObject +{ + public int MyInt { get; set; } + public double MyDouble { get; set; } +} + +class Program +{ + static void Main() + { + var data = new DataObject + { + MyInt = 5, + MyDouble = 5.6 + }; + var a = 1; + } +}"; + await VerifyCSharpFixAsync(source, fixtest, 0); + } + [Fact] public async Task ObjectCreationWithoutConstructorDoesNotCreateDiagnostic() { From d9884575ccaf5ab8c369db0d54fa7173132f2f19 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Wed, 17 Feb 2016 23:32:03 -0200 Subject: [PATCH 012/234] Add PR and issue templates, move CONTRIBUTING --- CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 .github/ISSUE_TEMPLATE.md | 46 ++++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 16 ++++++++ 3 files changed, 62 insertions(+) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..0f17d7434 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,46 @@ +#New analyzer: + +Input your analyzer description. + +Before: + +````csharp +//your code that triggers the diagnostic +```` + +After: + +````csharp +//your code after the fix has been applied +```` + +You can add more information here, e.g. conditions under which a diagnostic should not trigger, etc. + +Diagnostic Id: `CC0000` (take a number and update the [wiki](https://github.com/code-cracker/code-cracker/wiki/DiagnosticIds)) +Category: `` (see [supported categories](https://github.com/code-cracker/code-cracker/blob/master/src/Common/CodeCracker.Common/SupportedCategories.cs) and their [descriptions](https://github.com/code-cracker/code-cracker/issues/97)) +Severity: `Hidden | Info | Warning | Error` (see the [descriptions](https://github.com/code-cracker/code-cracker/#severity-levels)) + +#Bug + +Input your bug description. Make sure you describe the steps to reproduce, +that you are working with the latest version, and the issue has not been reported yet. + +Example: (don't use your project code, use a sample that anyone could use to verify the bug, +so, for example, +don't use classes that are not part of the BCL or declared on your sample.) + +````csharp +//the code that reproduces the bug +```` + +Current output after fix applied (if it is a code fix bug): + +````csharp +//code fixed incorrectly +```` + +Expected output after fix applied (if it is a code fix bug): + +````csharp +//code fixed incorrectly +```` \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..f1fc8739d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +#Info (delete this section) +Please see the [contributing guide](https://github.com/code-cracker/code-cracker/blob/master/README.md#contributing), on the contributing section. + +You should notify the maintainers on the issue you are working on before you send a PR. + +[Rebase](http://gitready.com/intermediate/2009/01/31/intro-to-rebase.html) and +[squash](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) your commits. +Submit one commit only, on top of the branch you are working on, `master` for bug fixes to the +stable version, `vnext` to new analyzers and fixers. + +Verify if you pass the [definition of done](https://github.com/code-cracker/code-cracker#definition-of-done). + +Always reference issue you are fixing (see bellow, e.g. `Fixes #123`) + +#Start your PR description here (delete this line too) +Fixes # . \ No newline at end of file From ac90db1d071b367bf7ff4e447f65a865d60d51bf Mon Sep 17 00:00:00 2001 From: float4 <> Date: Fri, 19 Feb 2016 09:49:56 +0200 Subject: [PATCH 013/234] Fixed introduce field from constructor for struct --- .../Extensions/CSharpAnalyzerExtensions.cs | 15 ++++ .../IntroduceFieldFromConstructorAnalyzer.cs | 4 ++ ...duceFieldFromConstructorCodeFixProvider.cs | 17 ++--- .../IntroduceFieldFromConstructorTest.cs | 70 +++++++++++++++++++ 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 0d82e7692..095b7991c 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -707,5 +707,20 @@ public static SyntaxTokenList GetTokens(this Accessibility accessibility) throw new NotSupportedException(); } } + public static TypeDeclarationSyntax WithMembers(this TypeDeclarationSyntax typeDeclarationSyntax, SyntaxList members) + { + if (typeDeclarationSyntax is ClassDeclarationSyntax) + { + return (typeDeclarationSyntax as ClassDeclarationSyntax).WithMembers(members); + } + else if (typeDeclarationSyntax is StructDeclarationSyntax) + { + return (typeDeclarationSyntax as StructDeclarationSyntax).WithMembers(members); + } + else + { + throw new NotSupportedException(); + } + } } } diff --git a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs index aada36ec3..91562e3db 100644 --- a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs @@ -34,6 +34,10 @@ private static void AnalyzeConstructor(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; var constructorMethod = (ConstructorDeclarationSyntax)context.Node; + + var type = constructorMethod.FirstAncestorOrSelf(); + if (type == null || !(type is ClassDeclarationSyntax || type is StructDeclarationSyntax)) return; + var parameters = constructorMethod.ParameterList.Parameters; if (constructorMethod.Body == null) return; diff --git a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs index ed2730ca6..085196f21 100644 --- a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs @@ -42,11 +42,12 @@ public async static Task IntroduceFieldFromConstructorDocumentAsync(Do public static SyntaxNode IntroduceFieldFromConstructor(SyntaxNode root, ConstructorDeclarationSyntax constructorStatement, ParameterSyntax parameter) { - var oldClass = constructorStatement.FirstAncestorOrSelf(); - var newClass = oldClass; + // There are no constructors in interfaces, therefore all types remaining type (class and struct) are fine. + var oldType = constructorStatement.FirstAncestorOrSelf(); + var newType = oldType; var fieldName = parameter.Identifier.ValueText; var fieldType = parameter.Type; - var members = ExtractMembersFromClass(oldClass.Members); + var members = ExtractMembersFromClass(oldType.Members); var addMember = false; if (!members.Any(p => p.Key == fieldName && p.Value == fieldType.ToString())) @@ -62,7 +63,7 @@ public static SyntaxNode IntroduceFieldFromConstructor(SyntaxNode root, Construc SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(fieldName)), SyntaxFactory.IdentifierName(parameter.Identifier.ValueText))); var newConstructor = constructorStatement.WithBody(constructorStatement.Body.AddStatements(assignmentField)); - newClass = newClass.ReplaceNode(constructorStatement, newConstructor); + newType = newType.ReplaceNode(constructorStatement, newConstructor); if (addMember) { @@ -70,16 +71,16 @@ public static SyntaxNode IntroduceFieldFromConstructor(SyntaxNode root, Construc .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName))))) .WithModifiers(SyntaxFactory.TokenList(new[] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) })) .WithAdditionalAnnotations(Formatter.Annotation); - newClass = newClass.WithMembers(newClass.Members.Insert(0, newField)).WithoutAnnotations(Formatter.Annotation); + newType = newType.WithMembers(newType.Members.Insert(0, newField)).WithoutAnnotations(Formatter.Annotation); } - var newRoot = root.ReplaceNode(oldClass, newClass); + var newRoot = root.ReplaceNode(oldType, newType); return newRoot; } - private static Dictionary ExtractMembersFromClass(SyntaxList classMembers) + private static Dictionary ExtractMembersFromClass(SyntaxList typeMembers) { var members = new Dictionary(); - foreach (var m in classMembers) + foreach (var m in typeMembers) { var name = ""; if (m.IsKind(SyntaxKind.MethodDeclaration)) diff --git a/test/CSharp/CodeCracker.Test/Refactoring/IntroduceFieldFromConstructorTest.cs b/test/CSharp/CodeCracker.Test/Refactoring/IntroduceFieldFromConstructorTest.cs index fe1b72bf7..e0bac6a01 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/IntroduceFieldFromConstructorTest.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/IntroduceFieldFromConstructorTest.cs @@ -27,6 +27,76 @@ public TypeName(int par) await VerifyCSharpHasNoDiagnosticsAsync(test); } + [Fact] + public async Task WhenConstructorInMidlleOfNoWhere() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + public TypeName(int par) + { + this.par = par; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + + [Fact] + public async Task WhenConstructorOfStruct() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + struct TypeName + { + public TypeName(int par) + { + } + } + }"; + + const string expected = @" + using System; + + namespace ConsoleApplication1 + { + struct TypeName + { + private readonly int par; + + public TypeName(int par) + { + this.par = par; + } + } + }"; + await VerifyCSharpFixAsync(test, expected); + } + + [Fact] + public async Task WhenConstructorOfInterface() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + interface TypeName + { + public TypeName(int par) + { + this.par = par; + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + [Fact] public async Task WhenConstructorParameterHasPrivateReadOnlyField() { From 4f272bc6ac472bfcf2f66138a0cb3b669ca303dd Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 20 Feb 2016 08:45:55 -0200 Subject: [PATCH 014/234] Fix to do not run CC0090 on generated files Fixes #720 --- .../CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs index 7da0fa90a..f4da96669 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs @@ -29,6 +29,7 @@ public sealed class XmlDocumentationAnalyzer : DiagnosticAnalyzer private static void Analyzer(SyntaxNodeAnalysisContext context) { + if (context.IsGenerated()) return; var documentationNode = (DocumentationCommentTriviaSyntax)context.Node; var method = GetMethodFromXmlDocumentation(documentationNode); if (method == null) return; From 596ba55240a5ab90fad1deff3fd6f779572faacb Mon Sep 17 00:00:00 2001 From: carloscds Date: Mon, 1 Feb 2016 22:44:04 -0200 Subject: [PATCH 015/234] Fix #698 Fix error when ValueType Intermediate commit Fix final --- .../CodeCracker/Style/ForInArrayAnalyzer.cs | 23 ++++++- .../CodeCracker.Test/Style/ForInArrayTests.cs | 60 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs b/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs index 300462f5e..f8f56457b 100644 --- a/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs @@ -65,7 +65,6 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) return !identifierSymbol.Equals(arrayId); }); if (otherUsesOfIndexToken != 0) return; - var arrayAccessorSymbols = (from s in forBlock.Statements.OfType() where s.Declaration.Variables.Count == 1 let declaration = s.Declaration.Variables.First() @@ -77,6 +76,28 @@ where controlVarId.Equals(initSymbol) where arrayId.Equals(someArrayInit) select arrayId).ToList(); if (!arrayAccessorSymbols.Any()) return; + var valueTypeVariable = (from s in forBlock.Statements.OfType() + where s.Declaration.Variables.Count == 1 + let symbol = semanticModel.GetDeclaredSymbol(s.Declaration.Variables.First()) as ISymbol + where ((ILocalSymbol)symbol).Type.IsValueType + select s).ToList(); + + foreach (var statement in forBlock.Statements.OfType()) + { + var left = (statement.Expression as AssignmentExpressionSyntax)?.Left; + var memberAccess = (left as MemberAccessExpressionSyntax)?.Expression; + var identifier = ""; + if (memberAccess?.GetType()?.Name == "IdentifierNameSyntax") + { + identifier = (memberAccess as IdentifierNameSyntax)?.Identifier.Text ?? ""; + } + else + { + var element = (memberAccess as ElementAccessExpressionSyntax)?.Expression; + identifier = (element as IdentifierNameSyntax)?.Identifier.Text ?? ""; + } + if (identifier == arrayId.Name && valueTypeVariable.Any()) return; + } var diagnostic = Diagnostic.Create(Rule, forStatement.ForKeyword.GetLocation()); context.ReportDiagnostic(diagnostic); } diff --git a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs index 6d1afa994..0aa1ede2b 100644 --- a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs @@ -757,5 +757,65 @@ public int[] Foo }; await VerifyCSharpDiagnosticAsync(source, expected); } + + [Fact] + public async Task WithValueTypeNoDiagnostic() + { + var source = @" + using System; + using System.Collections.Generic; + + namespace Test + { + struct Foo + { + public int X; + } + + public class bar + { + static void Goo() + { + var array = new Foo[1]; + for (int i = 0; i < array.Length; i++) + { + var actual = array[i]; + array[i].X = 5; + } + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task WithValueTypeListNoDiagnostic() + { + var source = @" + using System; + using System.Collections.Generic; + + namespace Test + { + struct Foo + { + public int X; + } + + public class bar + { + static void Goo() + { + var array = new List(); + for (int i = 0; i < array.Length; i++) + { + var actual = array[i]; + array[i].X = 5; + } + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From 2a7b3fa6109e445b83230dbd656c91b1d5c08ef1 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 22 Feb 2016 10:48:43 -0300 Subject: [PATCH 016/234] Verify value types in for analyzer Closes #698 --- .../CodeCracker/Style/AlwaysUseVarAnalyzer.cs | 26 +-------------- .../CodeCracker/Style/ForInArrayAnalyzer.cs | 25 ++------------- .../Extensions/AnalyzerExtensions.cs | 24 ++++++++++++++ .../CodeCracker.Test/Style/ForInArrayTests.cs | 32 +++++++++++++++++++ 4 files changed, 60 insertions(+), 47 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/AlwaysUseVarAnalyzer.cs b/src/CSharp/CodeCracker/Style/AlwaysUseVarAnalyzer.cs index dc412018c..7e5c5aab2 100644 --- a/src/CSharp/CodeCracker/Style/AlwaysUseVarAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/AlwaysUseVarAnalyzer.cs @@ -71,33 +71,9 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) } } - var rule = IsPrimitvie(variableType) ? RulePrimitives : RuleNonPrimitives; + var rule = variableType.IsPrimitive() ? RulePrimitives : RuleNonPrimitives; var diagnostic = Diagnostic.Create(rule, variableDeclaration.Type.GetLocation()); context.ReportDiagnostic(diagnostic); } - - private static bool IsPrimitvie(ITypeSymbol typeSymbol) - { - switch (typeSymbol.SpecialType) - { - case SpecialType.System_Boolean: - case SpecialType.System_Byte: - case SpecialType.System_SByte: - case SpecialType.System_Int16: - case SpecialType.System_UInt16: - case SpecialType.System_Int32: - case SpecialType.System_UInt32: - case SpecialType.System_Int64: - case SpecialType.System_UInt64: - case SpecialType.System_IntPtr: - case SpecialType.System_UIntPtr: - case SpecialType.System_Char: - case SpecialType.System_Double: - case SpecialType.System_Single: - return true; - default: - return false; - } - } } } \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs b/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs index f8f56457b..1a95477bf 100644 --- a/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs @@ -69,6 +69,9 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) where s.Declaration.Variables.Count == 1 let declaration = s.Declaration.Variables.First() where declaration?.Initializer?.Value is ElementAccessExpressionSyntax + let iterableSymbol = semanticModel.GetDeclaredSymbol(declaration) + let iterableType = ((ILocalSymbol)iterableSymbol).Type + where !(iterableType.IsPrimitive() ^ iterableType.IsValueType) let init = (ElementAccessExpressionSyntax)declaration.Initializer.Value let initSymbol = semanticModel.GetSymbolInfo(init.ArgumentList.Arguments.First().Expression).Symbol where controlVarId.Equals(initSymbol) @@ -76,28 +79,6 @@ where controlVarId.Equals(initSymbol) where arrayId.Equals(someArrayInit) select arrayId).ToList(); if (!arrayAccessorSymbols.Any()) return; - var valueTypeVariable = (from s in forBlock.Statements.OfType() - where s.Declaration.Variables.Count == 1 - let symbol = semanticModel.GetDeclaredSymbol(s.Declaration.Variables.First()) as ISymbol - where ((ILocalSymbol)symbol).Type.IsValueType - select s).ToList(); - - foreach (var statement in forBlock.Statements.OfType()) - { - var left = (statement.Expression as AssignmentExpressionSyntax)?.Left; - var memberAccess = (left as MemberAccessExpressionSyntax)?.Expression; - var identifier = ""; - if (memberAccess?.GetType()?.Name == "IdentifierNameSyntax") - { - identifier = (memberAccess as IdentifierNameSyntax)?.Identifier.Text ?? ""; - } - else - { - var element = (memberAccess as ElementAccessExpressionSyntax)?.Expression; - identifier = (element as IdentifierNameSyntax)?.Identifier.Text ?? ""; - } - if (identifier == arrayId.Name && valueTypeVariable.Any()) return; - } var diagnostic = Diagnostic.Create(Rule, forStatement.ForKeyword.GetLocation()); context.ReportDiagnostic(diagnostic); } diff --git a/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs b/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs index af2272c40..b7bd2ee4f 100644 --- a/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs +++ b/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs @@ -166,5 +166,29 @@ public static Accessibility GetMinimumCommonAccessibility(this Accessibility acc throw new NotSupportedException(); } } + + public static bool IsPrimitive(this ITypeSymbol typeSymbol) + { + switch (typeSymbol.SpecialType) + { + case SpecialType.System_Boolean: + case SpecialType.System_Byte: + case SpecialType.System_SByte: + case SpecialType.System_Int16: + case SpecialType.System_UInt16: + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_IntPtr: + case SpecialType.System_UIntPtr: + case SpecialType.System_Char: + case SpecialType.System_Double: + case SpecialType.System_Single: + return true; + default: + return false; + } + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs index 0aa1ede2b..7b333410e 100644 --- a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs @@ -788,6 +788,38 @@ static void Goo() await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task WithValueTypeAndIEnumeratorDoesNotCreateDiagnostic() + { + var source = @" +class Foo +{ + void Bar() + { + var list = new MyList(); + for (int i = 0; i < list.Count; i++) + { + var actual = list[i]; + actual.X = 5; + } + } +} +struct Struct +{ + public int X { get; set; } +} +class MyList +{ + public int Count => 1; + public Struct this[int index] => new Struct(); + public System.Collections.Generic.IEnumerator GetEnumerator() + { + yield return new Struct(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task WithValueTypeListNoDiagnostic() { From 25516071b9512433c9d373667067ba955968a2ac Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 26 Feb 2016 00:11:53 -0300 Subject: [PATCH 017/234] Ignore Disposable Variable when object could live longer Passed to methods. Assigned to properties. Fixes #465 --- .../DisposableVariableNotDisposedAnalyzer.cs | 26 ++++-- .../DisposableVariableNotDisposedTests.cs | 80 ++++++++++++++----- 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index fc3cbe6d9..9901b2114 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -107,16 +107,30 @@ private static bool IsDisposedOrAssigned(SemanticModel semanticModel, StatementS var method = statement.FirstAncestorOrSelf(); if (method == null) return false; if (IsReturned(method, statement, semanticModel, identitySymbol)) return true; - foreach (var childStatements in method.Body.DescendantNodes().OfType()) + foreach (var childStatement in method.Body.DescendantNodes().OfType()) { - if (childStatements.SpanStart > statement.SpanStart - && (IsCorrectDispose(childStatements as ExpressionStatementSyntax, semanticModel, identitySymbol) - || IsAssignedToField(childStatements as ExpressionStatementSyntax, semanticModel, identitySymbol))) + if (childStatement.SpanStart > statement.SpanStart + && (IsCorrectDispose(childStatement as ExpressionStatementSyntax, semanticModel, identitySymbol) + || IsPassedAsArgument(childStatement, semanticModel, identitySymbol) + || IsAssignedToFieldOrProperty(childStatement as ExpressionStatementSyntax, semanticModel, identitySymbol))) return true; } return false; } + private static bool IsPassedAsArgument(StatementSyntax statement, SemanticModel semanticModel, ILocalSymbol identitySymbol) + { + if (statement == null) return false; + var args = statement.DescendantNodes().OfKind(SyntaxKind.Argument); + foreach (var arg in args) + { + var argSymbol = semanticModel.GetSymbolInfo(arg.Expression).Symbol; + if (identitySymbol.Equals(argSymbol)) return true; + } + return false; + } + + private static bool IsReturned(MethodDeclarationSyntax method, StatementSyntax statement, SemanticModel semanticModel, ILocalSymbol identitySymbol) { var anonymousFunction = statement.FirstAncestorOfKind(SyntaxKind.ParenthesizedLambdaExpression, @@ -147,13 +161,13 @@ private static bool IsReturned(MethodDeclarationSyntax method, StatementSyntax s return isReturning; } - private static bool IsAssignedToField(ExpressionStatementSyntax expressionStatement, SemanticModel semanticModel, ILocalSymbol identitySymbol) + private static bool IsAssignedToFieldOrProperty(ExpressionStatementSyntax expressionStatement, SemanticModel semanticModel, ILocalSymbol identitySymbol) { if (expressionStatement == null) return false; if (!expressionStatement.Expression.IsKind(SyntaxKind.SimpleAssignmentExpression)) return false; var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; var assignmentTarget = semanticModel.GetSymbolInfo(assignment.Left).Symbol; - if (assignmentTarget?.Kind != SymbolKind.Field) return false; + if (assignmentTarget?.Kind != SymbolKind.Field && assignmentTarget?.Kind != SymbolKind.Property) return false; var assignmentSource = semanticModel.GetSymbolInfo(assignment.Right).Symbol; return (identitySymbol.Equals(assignmentSource)); } diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index 60a80b3d0..ba53e0a9b 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -595,10 +595,10 @@ public async Task FixADisposableDeclarationWithoutDispose() public async Task FixADisposableDeclarationWithoutDisposeWithStatementsAfter() { var source = @"var m = new System.IO.MemoryStream(); -Console.WriteLine(m);".WrapInCSharpMethod(); +m.Flush();".WrapInCSharpMethod(); var fixtest = @"using (var m = new System.IO.MemoryStream()) { - Console.WriteLine(m); + m.Flush(); }".WrapInCSharpMethod(); await VerifyCSharpFixAsync(source, fixtest); } @@ -609,14 +609,14 @@ public async Task FixADisposableDeclarationWithoutDisposeInsideBlock() var source = @"if (DateTime.Now.Second % 2 == 0) { var m = new System.IO.MemoryStream(); - Console.WriteLine(m); + m.Flush(); } Console.WriteLine(1);".WrapInCSharpMethod(); var fixtest = @"if (DateTime.Now.Second % 2 == 0) { using (var m = new System.IO.MemoryStream()) { - Console.WriteLine(m); + m.Flush(); } } Console.WriteLine(1);".WrapInCSharpMethod(); @@ -682,11 +682,11 @@ public async Task FixAssignmentWithStatementsAfter() { var source = @"System.IO.MemoryStream m; m = new System.IO.MemoryStream(); -Console.WriteLine(m);".WrapInCSharpMethod(); +m.Flush();".WrapInCSharpMethod(); var fixtest = @"System.IO.MemoryStream m; using (m = new System.IO.MemoryStream()) { - Console.WriteLine(m); + m.Flush(); }".WrapInCSharpMethod(); await VerifyCSharpFixAsync(source, fixtest); } @@ -932,7 +932,7 @@ public async Task FixAssignmentInsideBlock() { System.IO.MemoryStream m; m = new System.IO.MemoryStream(); - Console.WriteLine(m); + m.Flush(); } Console.WriteLine(1);".WrapInCSharpMethod(); var fixtest = @"if (DateTime.Now.Second % 2 == 0) @@ -940,7 +940,7 @@ public async Task FixAssignmentInsideBlock() System.IO.MemoryStream m; using (m = new System.IO.MemoryStream()) { - Console.WriteLine(m); + m.Flush(); } } Console.WriteLine(1);".WrapInCSharpMethod(); @@ -954,7 +954,7 @@ public async Task FixAssignmentInsideBlockWithDifferentScopeInDeclarationAndAssi if (DateTime.Now.Second % 2 == 0) { m = new System.IO.MemoryStream(); - Console.WriteLine(m); + m.Flush(); } Console.WriteLine(1);".WrapInCSharpMethod(); var fixtest = @"System.IO.MemoryStream m; @@ -962,7 +962,7 @@ public async Task FixAssignmentInsideBlockWithDifferentScopeInDeclarationAndAssi { using (m = new System.IO.MemoryStream()) { - Console.WriteLine(m); + m.Flush(); } } Console.WriteLine(1);".WrapInCSharpMethod(); @@ -976,7 +976,7 @@ public async Task FixAssignmentInsideBlockWithDifferentScopeInDeclarationAndAssi if (DateTime.Now.Second % 2 == 0) { m = new System.IO.MemoryStream(); - Console.WriteLine(m); + m.Flush(); } m.Flush(); Console.WriteLine(1);".WrapInCSharpMethod(); @@ -984,7 +984,7 @@ public async Task FixAssignmentInsideBlockWithDifferentScopeInDeclarationAndAssi if (DateTime.Now.Second % 2 == 0) { m = new System.IO.MemoryStream(); - Console.WriteLine(m); + m.Flush(); } m.Flush(); Console.WriteLine(1); @@ -1005,7 +1005,7 @@ void Foo() if (DateTime.Now.Second % 2 == 0) { m = new Disposable(); - Console.WriteLine(m); + m.Push(); } m.Flush(); Console.WriteLine(1); @@ -1015,6 +1015,7 @@ class Disposable : IDisposable { void IDisposable.Dispose() { } public void Flush() { } + public void Push() { } } "; const string fixtest = @" @@ -1027,7 +1028,7 @@ void Foo() if (DateTime.Now.Second % 2 == 0) { m = new Disposable(); - Console.WriteLine(m); + m.Push(); } m.Flush(); Console.WriteLine(1); @@ -1038,6 +1039,7 @@ class Disposable : IDisposable { void IDisposable.Dispose() { } public void Flush() { } + public void Push() { } } "; await VerifyCSharpFixAsync(source, fixtest); @@ -1147,7 +1149,7 @@ void Foo() if (DateTime.Now.Second % 2 == 0) { m = new Disposable(); - Console.WriteLine(m); + m.Push(); } m.Flush(); if (DateTime.Now.Second % 3 == 0) @@ -1160,6 +1162,7 @@ class Disposable : IDisposable { void IDisposable.Dispose() { } public void Flush() { } + public void Push() { } } "; const string fixtest = @" @@ -1172,7 +1175,7 @@ void Foo() if (DateTime.Now.Second % 2 == 0) { m = new Disposable(); - Console.WriteLine(m); + m.Push(); } m.Flush(); if (DateTime.Now.Second % 3 == 0) @@ -1185,6 +1188,7 @@ class Disposable : IDisposable { void IDisposable.Dispose() { } public void Flush() { } + public void Push() { } } "; await VerifyCSharpFixAsync(source, fixtest); @@ -1205,7 +1209,7 @@ void Foo() if (DateTime.Now.Second % 4 == 0) { m = new Disposable(); - Console.WriteLine(m); + m.Push(); } m.Flush(); } @@ -1219,6 +1223,7 @@ class Disposable : IDisposable { void IDisposable.Dispose() { } public void Flush() { } + public void Push() { } } "; const string fixtest = @" @@ -1233,7 +1238,7 @@ void Foo() if (DateTime.Now.Second % 4 == 0) { m = new Disposable(); - Console.WriteLine(m); + m.Push(); } m.Flush(); } @@ -1247,6 +1252,7 @@ class Disposable : IDisposable { void IDisposable.Dispose() { } public void Flush() { } + public void Push() { } } "; await VerifyCSharpFixAsync(source, fixtest); @@ -1493,5 +1499,43 @@ static void Baz() }"; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task IgnoreWhenPassedIntoMethod() + { + const string source = @" +using System.IO; +class Foo +{ + void Bar() + { + var m = new MemoryStream(); + Baz(m); + } + void Baz(MemoryStream m) { } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task IgnoreWhenAssignedToField() + { + const string source = @" +using System.IO; +class HoldsDisposable +{ + public MemoryStream Ms { get; set; } +} +class Foo +{ + void Bar() + { + var m = new MemoryStream(); + var h = new HoldsDisposable(); + h.Ms = m; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From b34e02edebd2f958f9563c45e89df6f7d2265a33 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 27 Feb 2016 12:08:32 -0300 Subject: [PATCH 018/234] Use nodemon to watch files --- runTestsCS.ps1 | 51 +++++++++++++------------------------------------- runTestsVB.ps1 | 51 +++++++++++++------------------------------------- 2 files changed, 26 insertions(+), 76 deletions(-) diff --git a/runTestsCS.ps1 b/runTestsCS.ps1 index 622e9718e..4a24efe74 100644 --- a/runTestsCS.ps1 +++ b/runTestsCS.ps1 @@ -1,33 +1,20 @@ param([String]$testClass) -$Global:lastRun = $lastRun = [System.DateTime]::Now $testDllDirPath = "$PSScriptRoot\test\CSharp\CodeCracker.Test\bin\Debug\" $testDllFileName = "CodeCracker.Test.CSharp.dll" -$Global:testDllFullFileName = "$testDllDirPath$testDllFileName" -$Global:xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" +$testDllFullFileName = "$testDllDirPath$testDllFileName" +$xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" -if ($testClass -eq "now"){ - . $Global:xunitConsole "$Global:testDllFullFileName" +if (!(gcm nodemon -ErrorAction Ignore)) { + Write-Host -ForegroundColor DarkRed 'Nodemon not found, install it with npm: `npm i -g nodemon`' return } -function global:DebounceXunit { - try { - if (([System.DateTime]::Now - $script:lastRun).TotalMilliseconds -lt 2000) { - return - } - $Global:lastRun = [System.DateTime]::Now - If ($Global:testClass) { - Start-Process $Global:xunitConsole -ArgumentList "`"$Global:testDllFullFileName`" -class $Global:testClass" -NoNewWindow - } Else { - Start-Process $Global:xunitConsole -ArgumentList "`"$Global:testDllFullFileName`"" -NoNewWindow - } - } - catch - { - Write-Host $_.Exception.Message - } +if ($testClass -eq "now"){ + . $xunitConsole "$testDllFullFileName" + return } + Write-Host "Watching $testDllDirPath" If ($testClass) { If ($testClass.StartsWith("CodeCracker.Test") -eq $false) { @@ -35,21 +22,9 @@ If ($testClass) { } Write-Host "Only for $testClass" } -$Global:testClass = $testClass -try { - $watcher = New-Object System.IO.FileSystemWatcher - $watcher.Path = $testDllDirPath - $watcher.Filter = $testDllFileName - $watcher.IncludeSubdirectories = $false - $watcher.EnableRaisingEvents = $true - $watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite - $changed = Register-ObjectEvent $watcher "Changed" -Action { DebounceXunit } -} -catch { - Write-Host $_.Exception.Message -} -#if we do that, then we don't get any console output: -#Write-Host "Press any key to continue ..." -#[System.Console]::ReadKey() -#Unregister-Event $changed.Id +If ($testClass) { + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" --verbose +} Else { + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" --verbose +} \ No newline at end of file diff --git a/runTestsVB.ps1 b/runTestsVB.ps1 index 53e5730ea..30ecc0e14 100644 --- a/runTestsVB.ps1 +++ b/runTestsVB.ps1 @@ -1,33 +1,20 @@ param([String]$testClass) -$Global:lastRun = $lastRun = [System.DateTime]::Now $testDllDirPath = "$PSScriptRoot\test\VisualBasic\CodeCracker.Test\bin\Debug\" $testDllFileName = "CodeCracker.Test.VisualBasic.dll" -$Global:testDllFullFileName = "$testDllDirPath$testDllFileName" -$Global:xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" +$testDllFullFileName = "$testDllDirPath$testDllFileName" +$xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" -if ($testClass -eq "now"){ - . $Global:xunitConsole "$Global:testDllFullFileName" +if (!(gcm nodemon -ErrorAction Ignore)) { + Write-Host -ForegroundColor DarkRed 'Nodemon not found, install it with npm: `npm i -g nodemon`' return } -function global:DebounceXunit { - try { - if (([System.DateTime]::Now - $script:lastRun).TotalMilliseconds -lt 2000) { - return - } - $Global:lastRun = [System.DateTime]::Now - If ($Global:testClass) { - Start-Process $Global:xunitConsole -ArgumentList "`"$Global:testDllFullFileName`" -class $Global:testClass" -NoNewWindow - } Else { - Start-Process $Global:xunitConsole -ArgumentList "`"$Global:testDllFullFileName`"" -NoNewWindow - } - } - catch - { - Write-Host $_.Exception.Message - } +if ($testClass -eq "now"){ + . $xunitConsole "$testDllFullFileName" + return } + Write-Host "Watching $testDllDirPath" If ($testClass) { If ($testClass.StartsWith("CodeCracker.Test") -eq $false) { @@ -35,21 +22,9 @@ If ($testClass) { } Write-Host "Only for $testClass" } -$Global:testClass = $testClass -try { - $watcher = New-Object System.IO.FileSystemWatcher - $watcher.Path = $testDllDirPath - $watcher.Filter = $testDllFileName - $watcher.IncludeSubdirectories = $false - $watcher.EnableRaisingEvents = $true - $watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite - $changed = Register-ObjectEvent $watcher "Changed" -Action { DebounceXunit } -} -catch { - Write-Host $_.Exception.Message -} -#if we do that, then we don't get any console output: -#Write-Host "Press any key to continue ..." -#[System.Console]::ReadKey() -#Unregister-Event $changed.Id +If ($testClass) { + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" --verbose +} Else { + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" --verbose +} \ No newline at end of file From 5bef7bdd824b3522f45afb6c3057a5893b6412b0 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 27 Feb 2016 13:28:21 -0300 Subject: [PATCH 019/234] Do not make a method static if it takes RoutedEventArgs --- .../Design/MakeMethodStaticAnalyzer.cs | 8 ++++++++ .../Design/MakeMethodStaticTests.cs | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs b/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs index d8dc98556..b5c5a60b4 100644 --- a/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using System.Linq; using System.Collections.Immutable; +using System; namespace CodeCracker.CSharp.Design { @@ -80,11 +81,18 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) if (IsTestMethod(method, methodSymbol)) return; if (IsWebFormsMethod(methodSymbol)) return; if (IsGetEnumerator(methodSymbol)) return; + if (HasRoutedEventArgs(methodSymbol)) return; var diagnostic = Diagnostic.Create(Rule, method.Identifier.GetLocation(), method.Identifier.ValueText); context.ReportDiagnostic(diagnostic); } + private static bool HasRoutedEventArgs(IMethodSymbol methodSymbol) + { + var routedEventArgsParameters = methodSymbol.Parameters.Where(p => p.Type.ToString() == "System.Windows.RoutedEventArgs"); + return routedEventArgsParameters.Any(); + } + private static readonly string[] webFormsMethods = { "Application_AuthenticateRequest", "Application_BeginRequest", "Application_End", "Application_EndRequest", diff --git a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs index cafcd4950..9a1590393 100644 --- a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs @@ -1062,5 +1062,22 @@ public static void N() { } }; await VerifyCSharpDiagnosticAsync(source, expected); } + + [Fact] + public async Task IgnoreMethodsWithRoutedEventArgs() + { + const string source = @" +public class MainWindow +{ + void Window_Loaded(object sender, System.Windows.RoutedEventArgs e) + { + } +} +namespace System.Windows +{ + public class RoutedEventArgs : System.EventArgs { } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From e6e2fcca556b57dc5e34e44605c52d439e984853 Mon Sep 17 00:00:00 2001 From: carloscds Date: Sun, 28 Feb 2016 22:18:54 -0300 Subject: [PATCH 020/234] Fix #724 --- .../Style/TernaryOperatorCodeFixProviders.vb | 15 ++++++--- .../Style/TernaryOperatorTests.vb | 31 +++++++++++++++++-- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb index 6b24f9e72..2bb07719c 100644 --- a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb +++ b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb @@ -111,6 +111,15 @@ Namespace Style EnsureNothingAsType(semanticModel, type, typeSyntax). ConvertToBaseType(elseType, type) + If ifAssign.OperatorToken.Text <> "=" Then + trueExpression = ifAssign.Right. + EnsureNothingAsType(semanticModel, type, typeSyntax). + ConvertToBaseType(ifType, type) + + falseExpression = elseAssign.Right. + EnsureNothingAsType(semanticModel, type, typeSyntax). + ConvertToBaseType(elseType, type) + End If Dim leadingTrivia = ifBlock.GetLeadingTrivia. AddRange(ifAssign.GetLeadingTrivia()). @@ -122,13 +131,11 @@ Namespace Style InsertRange(0, elseAssign.GetTrailingTrivia().Where(Function(trivia) Not trivia.IsKind(SyntaxKind.EndOfLineTrivia))). InsertRange(0, ifAssign.GetTrailingTrivia().Where(Function(trivia) Not trivia.IsKind(SyntaxKind.EndOfLineTrivia))) - Dim ternary = SyntaxFactory.TernaryConditionalExpression(ifBlock.IfStatement.Condition.WithoutTrailingTrivia(), trueExpression.WithoutTrailingTrivia(), - falseExpression.WithoutTrailingTrivia()). - WithAdditionalAnnotations(Formatter.Annotation) + falseExpression.WithoutTrailingTrivia()) - Dim assignment = SyntaxFactory.SimpleAssignmentStatement(ifAssign.Left.WithLeadingTrivia(leadingTrivia), ternary). + Dim assignment = SyntaxFactory.SimpleAssignmentStatement(ifAssign.Left.WithLeadingTrivia(leadingTrivia), ifAssign.OperatorToken, ternary). WithTrailingTrivia(trailingTrivia). WithAdditionalAnnotations(Formatter.Annotation) diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index ef72d758e..1ebcd9273 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -432,6 +432,34 @@ End Class" Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) End Function + + Public Async Function WhenUsingAssignmentOperatorReturnSameAssignment() As Task + Const source = " +Class MyType + Public Sub x2() + Dim output As String = String.Empty + Dim test As Boolean + test = True + If test Then + output += ""True"" + Else + output += ""False"" + End If + End Sub +End Class" + + Const fix = " +Class MyType + Public Sub x2() + Dim output As String = String.Empty + Dim test As Boolean + test = True + output += If(test, ""True"", ""False"") + End Sub +End Class" + + Await VerifyBasicFixAsync(source, fix, formatBeforeCompare:=True) + End Function End Class @@ -671,6 +699,7 @@ End Namespace" Await VerifyBasicFixAllAsync(New String() {sourceReturn, sourceReturn.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) End Function + End Class Public Class TernaryOperatorFromIifTests @@ -804,7 +833,5 @@ End Class" Await VerifyBasicHasNoDiagnosticsAsync(source) End Function - - End Class From 1c69d6b3e05ce041189a26874a755edf980666a9 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 3 Mar 2016 11:56:32 -0300 Subject: [PATCH 021/234] Remove verbose from nodemon --- runTestsCS.ps1 | 4 ++-- runTestsVB.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/runTestsCS.ps1 b/runTestsCS.ps1 index 4a24efe74..bc640573f 100644 --- a/runTestsCS.ps1 +++ b/runTestsCS.ps1 @@ -24,7 +24,7 @@ If ($testClass) { } If ($testClass) { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" --verbose + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" } Else { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" --verbose + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" } \ No newline at end of file diff --git a/runTestsVB.ps1 b/runTestsVB.ps1 index 30ecc0e14..d2fe0644e 100644 --- a/runTestsVB.ps1 +++ b/runTestsVB.ps1 @@ -24,7 +24,7 @@ If ($testClass) { } If ($testClass) { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" --verbose + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" } Else { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" --verbose + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" } \ No newline at end of file From 7fb90f40edbd450b40db7f8b861c4912287f0ab0 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 15 Mar 2016 01:02:36 -0300 Subject: [PATCH 022/234] Fix Make Ternary for VB when it has comments Closes #725 for CC0013 --- .../Style/TernaryOperatorCodeFixProviders.vb | 4 +- .../Style/TernaryOperatorTests.vb | 549 ++++++++++-------- 2 files changed, 308 insertions(+), 245 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb index 2bb07719c..11d68892c 100644 --- a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb +++ b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb @@ -49,8 +49,8 @@ Namespace Style EnsureNothingAsType(semanticModel, type, typeSyntax) Dim leadingTrivia = ifBlock.GetLeadingTrivia() - leadingTrivia = leadingTrivia.InsertRange(leadingTrivia.Count - 1, ifReturn.GetLeadingTrivia().Where(Function(trivia) trivia.IsKind(SyntaxKind.CommentTrivia))) - leadingTrivia = leadingTrivia.InsertRange(leadingTrivia.Count - 1, elseReturn.GetLeadingTrivia().Where(Function(trivia) trivia.IsKind(SyntaxKind.CommentTrivia))) + leadingTrivia = leadingTrivia.InsertRange(leadingTrivia.Count - 1, ifReturn.GetLeadingTrivia()) + leadingTrivia = leadingTrivia.InsertRange(leadingTrivia.Count - 1, elseReturn.GetLeadingTrivia()) Dim trailingTrivia = ifBlock.GetTrailingTrivia. InsertRange(0, elseReturn.GetTrailingTrivia().Where(Function(trivia) Not trivia.IsKind(SyntaxKind.EndOfLineTrivia))). diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index 1ebcd9273..89c3787a8 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -1,11 +1,12 @@ Imports CodeCracker.VisualBasic.Style Imports Xunit -Public Class TernaryOperatorWithAssignmentTests - Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorWithAssignmentCodeFixProvider) +Namespace Style + Public Class TernaryOperatorWithAssignmentTests + Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorWithAssignmentCodeFixProvider) - Public Async Function WhenUsingIfWithoutElseAnalyzerDoesNotCreateDiagnostic() As Task - Const sourceWithoutElse = " + Public Async Function WhenUsingIfWithoutElseAnalyzerDoesNotCreateDiagnostic() As Task + Const sourceWithoutElse = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -17,12 +18,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithoutElse) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithoutElse) + End Function - - Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnIfAnalyzerDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnIfAnalyzerDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -37,12 +38,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnElseAnalyzerDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnElseAnalyzerDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -57,12 +58,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfWithElseButWithoutReturnOnElseDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButWithoutReturnOnElseDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -77,12 +78,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfWithElseButIfBlockWithoutReturnDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButIfBlockWithoutReturnDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -97,12 +98,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIElseIfDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIElseIfDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -117,12 +118,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfElseIfElseDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfElseIfElseDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -137,21 +138,21 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfAndElseWithDirectReturnAnalyzerCreatesDiagnostic() As Task - Dim expected As New DiagnosticResult With { - .Id = DiagnosticId.TernaryOperator_Assignment.ToDiagnosticId(), - .Message = "You can use a ternary operator.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 8, 13)} - } - Await VerifyBasicDiagnosticAsync(sourceAssign, expected) - End Function + + Public Async Function WhenUsingIfAndElseWithDirectReturnAnalyzerCreatesDiagnostic() As Task + Dim expected As New DiagnosticResult With { + .Id = DiagnosticId.TernaryOperator_Assignment.ToDiagnosticId(), + .Message = "You can use a ternary operator.", + .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, + .Locations = {New DiagnosticResultLocation("Test0.vb", 8, 13)} + } + Await VerifyBasicDiagnosticAsync(sourceAssign, expected) + End Function - Private Const sourceAssign = " + Private Const sourceAssign = " Imports System Namespace ConsoleApplication1 Class MyType @@ -167,9 +168,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - - Public Async Function WhenUsingIfAndElseWithAssignmentChangeToTernaryFix() As Task - Const fix = " + + Public Async Function WhenUsingIfAndElseWithAssignmentChangeToTernaryFix() As Task + Const fix = " Imports System Namespace ConsoleApplication1 Class MyType @@ -180,12 +181,21 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicFixAsync(sourceAssign, fix) - End Function + Await VerifyBasicFixAsync(sourceAssign, fix) + End Function + Sub Foo() + Dim v As Boolean + If True Then + ' a comment + v = False + Else + v = True + End If + End Sub - - Public Async Function WhenUsingIfAndElseWithAssignmentChangeToTernaryFixAll() As Task - Const fix = " + + Public Async Function WhenUsingIfAndElseWithAssignmentChangeToTernaryFixAll() As Task + Const fix = " Imports System Namespace ConsoleApplication1 Class MyType @@ -196,12 +206,12 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicFixAllAsync(New String() {sourceAssign, sourceAssign.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) - End Function + Await VerifyBasicFixAllAsync(New String() {sourceAssign, sourceAssign.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) + End Function - - Public Async Function WhenTernaryWithObjectDoesApplyFix() As Task - Const source = " + + Public Async Function WhenTernaryWithObjectDoesApplyFix() As Task + Const source = " Class MyCustomer Public Property Value As String End Class @@ -221,7 +231,7 @@ Class Tester End Sub End Class" - Const fix = " + Const fix = " Class MyCustomer Public Property Value As String End Class @@ -237,13 +247,13 @@ Class Tester End Sub End Class" - Await VerifyBasicFixAsync(source, fix) + Await VerifyBasicFixAsync(source, fix) - End Function + End Function - - Public Async Function WhenUsingIfAndElseWithNullableValueTypeAssignmentChangeToTernaryFix() As Task - Const source = " + + Public Async Function WhenUsingIfAndElseWithNullableValueTypeAssignmentChangeToTernaryFix() As Task + Const source = " Public Class MyType Public Sub Foo() Dim a As Integer? @@ -255,7 +265,7 @@ Public Class MyType End Sub End Class" - Const fix = " + Const fix = " Public Class MyType Public Sub Foo() Dim a As Integer? @@ -263,13 +273,13 @@ Public Class MyType End Sub End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function - - Public Async Function FixConsidersBaseTypeAssignent() As Task - Const source = " + + Public Async Function FixConsidersBaseTypeAssignent() As Task + Const source = " Public Class Base End Class Public Class B @@ -286,7 +296,7 @@ Public Class MyType End Sub End Class" - Const fix = " + Const fix = " Public Class Base End Class Public Class B @@ -299,12 +309,12 @@ Public Class MyType End Sub End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function - - Public Async Function WhenUsingCommentsConcatenateAtEndOfTernary() As Task - Const source = " + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function + + Public Async Function WhenUsingCommentsConcatenateAtEndOfTernary() As Task + Const source = " Public Class MyType Public Sub Foo() Dim a As Integer @@ -316,7 +326,7 @@ Public Class MyType End Sub End Class" - Const fix = " + Const fix = " Public Class MyType Public Sub Foo() Dim a As Integer @@ -324,13 +334,13 @@ Public Class MyType End Sub End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function - - Public Async Function WhenUsingIfAndElseWithNullableValueTypeAssignmentChangeToTernaryFixAll() As Task - Const source = " + + Public Async Function WhenUsingIfAndElseWithNullableValueTypeAssignmentChangeToTernaryFixAll() As Task + Const source = " Public Class MyType Public Sub Foo() Dim a As Integer? @@ -342,7 +352,7 @@ Public Class MyType End Sub End Class" - Const fix = " + Const fix = " Public Class MyType Public Sub Foo() Dim a As Integer? @@ -350,24 +360,24 @@ Public Class MyType End Sub End Class" - Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) - End Function + Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) + End Function - - Public Async Function WhenUsingConcatenationAssignmentExpandsToConcatenateAtEndOfTernary() As Task - Const source = " + + Public Async Function WhenUsingConcatenationAssignmentExpandsToConcatenateAtEndOfTernary() As Task + Const source = " Public Class MyType Public Sub Foo() Dim x = ""test"" If True Then - x = ""1"" + x = ""1"" Else x &= ""2"" End If End Sub End Class" - Const fix = " + Const fix = " Public Class MyType Public Sub Foo() Dim x = ""test"" @@ -375,14 +385,14 @@ Public Class MyType End Sub End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function - - Public Async Function WhenUsingAddAssiginmentExpandsOperationProperly() As Task - Const source = " + + Public Async Function WhenUsingAddAssiginmentExpandsOperationProperly() As Task + Const source = " Public Class MyType Public Sub Foo() Dim x = 0 @@ -394,7 +404,7 @@ Public Class MyType End Sub End Class" - Const fix = " + Const fix = " Public Class MyType Public Sub Foo() Dim x = 0 @@ -402,13 +412,13 @@ Public Class MyType End Sub End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function - - Public Async Function WhenUsingSubtractAssiginmentExpandsOperationProperly() As Task - Const source = " + + Public Async Function WhenUsingSubtractAssiginmentExpandsOperationProperly() As Task + Const source = " Public Class MyType Public Sub Foo() Dim x = 0 @@ -420,7 +430,7 @@ Public Class MyType End Sub End Class" - Const fix = " + Const fix = " Public Class MyType Public Sub Foo() Dim x = 0 @@ -428,13 +438,13 @@ Public Class MyType End Sub End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function - - Public Async Function WhenUsingAssignmentOperatorReturnSameAssignment() As Task - Const source = " + + Public Async Function WhenUsingAssignmentOperatorReturnSameAssignment() As Task + Const source = " Class MyType Public Sub x2() Dim output As String = String.Empty @@ -448,7 +458,7 @@ Class MyType End Sub End Class" - Const fix = " + Const fix = " Class MyType Public Sub x2() Dim output As String = String.Empty @@ -458,18 +468,16 @@ Class MyType End Sub End Class" - Await VerifyBasicFixAsync(source, fix, formatBeforeCompare:=True) - End Function - - -End Class + Await VerifyBasicFixAsync(source, fix, formatBeforeCompare:=True) + End Function + End Class -Public Class TernaryOperatorWithReturnTests - Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorWithReturnCodeFixProvider) + Public Class TernaryOperatorWithReturnTests + Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorWithReturnCodeFixProvider) - - Public Async Function WhenUsingIfWithoutElseAnalyzerDoesNotCreateDiagnostic() As Task - Const sourceWithoutElse = " + + Public Async Function WhenUsingIfWithoutElseAnalyzerDoesNotCreateDiagnostic() As Task + Const sourceWithoutElse = " Namespace ConsoleApplication1 Class TypeName Public Function Foo() As Integer @@ -480,12 +488,12 @@ Namespace ConsoleApplication1 End Function End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithoutElse) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithoutElse) + End Function - - Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnIfAnalyzerDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnIfAnalyzerDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Function Foo() As Integer @@ -499,12 +507,12 @@ Namespace ConsoleApplication1 End Function End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnElseAnalyzerDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButWithBlockWith2StatementsOnElseAnalyzerDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Function Foo() As Integer @@ -518,12 +526,12 @@ Namespace ConsoleApplication1 End Function End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfWithElseButWithoutReturnOnElseDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButWithoutReturnOnElseDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Function Foo() As Integer @@ -536,12 +544,12 @@ Namespace ConsoleApplication1 End Function End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfWithElseButIfBlockWithoutReturnDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfWithElseButIfBlockWithoutReturnDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Function Foo() As Integer @@ -554,12 +562,12 @@ Namespace ConsoleApplication1 End Function End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIElseIfDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIElseIfDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Function Foo() As Integer @@ -573,13 +581,13 @@ Namespace ConsoleApplication1 End Function End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfAndElseWithNullableValueTypeDirectReturnChangeToTernaryFix() As Task - Const source = " + + Public Async Function WhenUsingIfAndElseWithNullableValueTypeDirectReturnChangeToTernaryFix() As Task + Const source = " Public Class MyType Public Function Foo() As Integer? If True Then @@ -590,20 +598,20 @@ Public Class MyType End Function End Class" - Const fix = " + Const fix = " Public Class MyType Public Function Foo() As Integer? Return If(True, 1, DirectCast(Nothing, Integer?)) End Function End Class" - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) - End Function + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function - - Public Async Function WhenUsingIfElseIfElseDoesNotCreate() As Task - Const sourceWithMultipleStatements = " + + Public Async Function WhenUsingIfElseIfElseDoesNotCreate() As Task + Const sourceWithMultipleStatements = " Namespace ConsoleApplication1 Class TypeName Public Sub Foo() @@ -617,13 +625,13 @@ Namespace ConsoleApplication1 End Sub End Class End Namespace" - Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(sourceWithMultipleStatements) + End Function - - Public Async Function WhenUsingIfAndElseWithNullableValueTypeDirectReturnChangeToTernaryFixAll() As Task - Const source = " + + Public Async Function WhenUsingIfAndElseWithNullableValueTypeDirectReturnChangeToTernaryFixAll() As Task + Const source = " Public Class MyType Public Function Foo() As Integer? If True Then @@ -634,17 +642,17 @@ Public Class MyType End Function End Class" - Const fix = " + Const fix = " Public Class MyType Public Function Foo() As Integer? Return If(True, 1, DirectCast(Nothing, Integer?)) End Function End Class" - Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) - End Function + Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) + End Function - Private Const sourceReturn = " + Private Const sourceReturn = " Namespace ConsoleApplication1 Class MyType Public Function Foo() As Integer @@ -658,20 +666,20 @@ Namespace ConsoleApplication1 End Class End Namespace" - - Public Async Function WhenUsingIfAndElseWithDirectReturnAnalyzerCreatesDiagnostic() As Task - Dim expected As New DiagnosticResult With { - .Id = DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), - .Message = "You can use a ternary operator.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 13)} - } - Await VerifyBasicDiagnosticAsync(sourceReturn, expected) - End Function + + Public Async Function WhenUsingIfAndElseWithDirectReturnAnalyzerCreatesDiagnostic() As Task + Dim expected As New DiagnosticResult With { + .Id = DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), + .Message = "You can use a ternary operator.", + .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, + .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 13)} + } + Await VerifyBasicDiagnosticAsync(sourceReturn, expected) + End Function - - Public Async Function WhenUsingIfAndElseWithDirectReturnCreatesFix() As Task - Const fix = " + + Public Async Function WhenUsingIfAndElseWithDirectReturnCreatesFix() As Task + Const fix = " Namespace ConsoleApplication1 Class MyType Public Function Foo() As Integer @@ -681,12 +689,12 @@ Namespace ConsoleApplication1 End Class End Namespace" - Await VerifyBasicFixAsync(sourceReturn, fix) - End Function + Await VerifyBasicFixAsync(sourceReturn, fix) + End Function - - Public Async Function WhenUsingIfAndElseWithDirectReturnCreatesFixAll() As Task - Const fix = " + + Public Async Function WhenUsingIfAndElseWithDirectReturnCreatesFixAll() As Task + Const fix = " Namespace ConsoleApplication1 Class MyType Public Function Foo() As Integer @@ -696,18 +704,73 @@ Namespace ConsoleApplication1 End Class End Namespace" - Await VerifyBasicFixAllAsync(New String() {sourceReturn, sourceReturn.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) - End Function + Await VerifyBasicFixAllAsync(New String() {sourceReturn, sourceReturn.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) + End Function + + Public Async Function FixCanWorkWithCommentsOnIf() As Task + Const source = " +Function s() As Boolean + If True Then + ' a comment + Return False 'b comment + Else + Return True + End If +End Function" + Const fix = " +Function s() As Boolean + ' a comment + Return If(True, False, True) 'b comment +End Function" + Await VerifyBasicFixAsync(source, fix) + End Function -End Class + Public Async Function FixCanWorkWithCommentsOnElse() As Task + Const source = " +Function s() As Boolean + If True Then + Return False + Else + ' a comment + Return True 'b comment + End If +End Function" + Const fix = " +Function s() As Boolean + ' a comment + Return If(True, False, True) 'b comment +End Function" + Await VerifyBasicFixAsync(source, fix) + End Function + + Public Async Function FixCanWorkWithCommentsOnIfAndElse() As Task + Const source = " +Function s() As Boolean + If True Then + ' a comment + Return False 'b comment + Else + ' c comment + Return True 'd comment + End If +End Function" + Const fix = " +Function s() As Boolean + ' a comment + ' c comment + Return If(True, False, True) 'b comment 'd comment +End Function" + Await VerifyBasicFixAsync(source, fix) + End Function + End Class -Public Class TernaryOperatorFromIifTests - Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorFromIifCodeFixProvider) + Public Class TernaryOperatorFromIifTests + Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorFromIifCodeFixProvider) - - Public Async Function WhenUsingIifAndSimpleAssignmentCreatesFix() As Task - Const source = " + + Public Async Function WhenUsingIifAndSimpleAssignmentCreatesFix() As Task + Const source = " Class TypeName Public Sub Foo() Dim x = 1 @@ -715,7 +778,7 @@ Class TypeName End Sub End Class" - Const fix = " + Const fix = " Class TypeName Public Sub Foo() Dim x = 1 @@ -723,12 +786,12 @@ Class TypeName End Sub End Class" - Await VerifyBasicFixAsync(source, fix) - End Function + Await VerifyBasicFixAsync(source, fix) + End Function - - Public Async Function WhenUsingIifAndSimpleAssignmentCreatesFixAll() As Task - Const source = " + + Public Async Function WhenUsingIifAndSimpleAssignmentCreatesFixAll() As Task + Const source = " Class MyType Public Sub Foo() Dim x = 1 @@ -736,7 +799,7 @@ Class MyType End Sub End Class" - Const fix = " + Const fix = " Class MyType Public Sub Foo() Dim x = 1 @@ -744,12 +807,12 @@ Class MyType End Sub End Class" - Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) - End Function + Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) + End Function - - Public Async Function WhenUsingIifAndReturnCreatesFix() As Task - Const source = " + + Public Async Function WhenUsingIifAndReturnCreatesFix() As Task + Const source = " Class MyType Public Function Foo() As Integer Dim x = 1 @@ -757,7 +820,7 @@ Class MyType End Function End Class" - Const fix = " + Const fix = " Class MyType Public Function Foo() As Integer Dim x = 1 @@ -765,20 +828,20 @@ Class MyType End Function End Class" - Dim expected As New DiagnosticResult With { - .Id = DiagnosticId.TernaryOperator_Iif.ToDiagnosticId(), - .Message = "You can use a ternary operator.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 16)} - } + Dim expected As New DiagnosticResult With { + .Id = DiagnosticId.TernaryOperator_Iif.ToDiagnosticId(), + .Message = "You can use a ternary operator.", + .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, + .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 16)} + } - Await VerifyBasicDiagnosticAsync(source, expected) - Await VerifyBasicFixAsync(source, fix) - End Function + Await VerifyBasicDiagnosticAsync(source, expected) + Await VerifyBasicFixAsync(source, fix) + End Function - - Public Async Function WhenUsingIifAndReturnCreatesFixAll() As Task - Const source = " + + Public Async Function WhenUsingIifAndReturnCreatesFixAll() As Task + Const source = " Class MyType Public Function Foo() As Integer Dim x = 1 @@ -786,7 +849,7 @@ Class MyType End Function End Class" - Const fix = " + Const fix = " Class MyType Public Function Foo() As Integer Dim x = 1 @@ -794,44 +857,44 @@ Class MyType End Function End Class" - Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) - End Function + Await VerifyBasicFixAllAsync(New String() {source, source.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) + End Function - - Public Async Function WhenNotUsingIifDoesNotCreateAnalyzer() As Task - Const source = " + + Public Async Function WhenNotUsingIifDoesNotCreateAnalyzer() As Task + Const source = " Class TypeName Public Sub Foo() Dim x = 1 End Sub End Class" - Await VerifyBasicHasNoDiagnosticsAsync(source) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(source) + End Function - - Public Async Function WhenIifWithTooManyParametersDoesNotCreateAnalyzer() As Task - Const source = " + + Public Async Function WhenIifWithTooManyParametersDoesNotCreateAnalyzer() As Task + Const source = " Class TypeName Public Sub Foo() Dim x = Iif(true, 1, 2, 3) End Sub End Class" - Await VerifyBasicHasNoDiagnosticsAsync(source) - End Function + Await VerifyBasicHasNoDiagnosticsAsync(source) + End Function - - Public Async Function WhenIifWithTooFewParametersDoesNotCreateAnalyzer() As Task - Const source = " + + Public Async Function WhenIifWithTooFewParametersDoesNotCreateAnalyzer() As Task + Const source = " Class TypeName Public Sub Foo() Dim x = Iif(true, 1) End Sub End Class" - Await VerifyBasicHasNoDiagnosticsAsync(source) - End Function - -End Class + Await VerifyBasicHasNoDiagnosticsAsync(source) + End Function + End Class +End Namespace From 9258e181ee4a7101837d2f19a65119097334ee70 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 15 Mar 2016 01:05:35 -0300 Subject: [PATCH 023/234] Enable Make Ternary for VB when it has leading comments Similar as #725, but for CC0014 --- .../CodeCracker/Style/TernaryOperatorAnalyzer.vb | 8 +++++--- .../CodeCracker.Test/Style/TernaryOperatorTests.vb | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Style/TernaryOperatorAnalyzer.vb b/src/VisualBasic/CodeCracker/Style/TernaryOperatorAnalyzer.vb index 7b498b661..81602adea 100644 --- a/src/VisualBasic/CodeCracker/Style/TernaryOperatorAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Style/TernaryOperatorAnalyzer.vb @@ -67,7 +67,6 @@ Namespace Style If TypeOf (ifClauseStatement) Is ReturnStatementSyntax AndAlso TypeOf (elseStatement) Is ReturnStatementSyntax Then - Dim diag = Diagnostic.Create(RuleForIfWithReturn, ifStatement.IfKeyword.GetLocation, "You can use a ternary operator.") context.ReportDiagnostic(diag) Exit Sub @@ -76,7 +75,10 @@ Namespace Style Dim ifAssignment = TryCast(ifClauseStatement, AssignmentStatementSyntax) Dim elseAssignment = TryCast(elseStatement, AssignmentStatementSyntax) If ifAssignment Is Nothing OrElse elseAssignment Is Nothing Then Exit Sub - If Not ifAssignment?.Left.IsEquivalentTo(elseAssignment?.Left) Then Exit Sub + Dim semanticModel = context.SemanticModel + Dim ifSymbol = semanticModel.GetSymbolInfo(ifAssignment.Left).Symbol + Dim elseSymbol = semanticModel.GetSymbolInfo(elseAssignment.Left).Symbol + If ifSymbol Is Nothing OrElse elseSymbol Is Nothing OrElse ifSymbol.Equals(elseSymbol) = False Then Exit Sub Dim assignDiag = Diagnostic.Create(RuleForIfWithAssignment, ifStatement.IfKeyword.GetLocation(), "You can use a ternary operator.") context.ReportDiagnostic(assignDiag) End Sub @@ -95,4 +97,4 @@ Namespace Style End If End Sub End Class -End Namespace +End Namespace \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index 89c3787a8..b363d18ba 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -319,8 +319,10 @@ Public Class MyType Public Sub Foo() Dim a As Integer If True Then + ' a a = 1 ' One Thing Else + ' b a = 2 ' Another End If End Sub @@ -330,6 +332,8 @@ End Class" Public Class MyType Public Sub Foo() Dim a As Integer + ' a + ' b a = If(True, 1, 2) ' One Thing ' Another End Sub End Class" From 847553ad153ff14490e9f3dea37095419caba729 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 27 Mar 2016 14:25:09 -0300 Subject: [PATCH 024/234] Allows verbatim identifiers with UnusedParametersAnalyzer Closes #741 --- .../Usage/UnusedParametersAnalyzer.cs | 8 +++-- .../Usage/UnusedParametersTests.cs | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs index a0fdedc2f..cec3e43ea 100644 --- a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs @@ -110,13 +110,15 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) private static bool IdentifierRefersToParam(IdentifierNameSyntax iName, ParameterSyntax param) { - if (iName.Identifier.ToString() != param.Identifier.ToString()) + var identifierName = iName.Identifier.ToString(); + if (!identifierName.StartsWith("@")) identifierName = $"@{identifierName}"; + var parameterName = param.Identifier.ToString(); + if (!parameterName.StartsWith("@")) parameterName = $"@{parameterName}"; + if (identifierName != parameterName) return false; - var mae = iName.Parent as MemberAccessExpressionSyntax; if (mae == null) return true; - return mae.DescendantNodes().FirstOrDefault() == iName; } diff --git a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs index 8402298ac..44cf5f2b9 100644 --- a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs @@ -58,6 +58,39 @@ public int Foo(int a) await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task UsedParameterWithVerbatimIdentifierDoesNotCreateDiagnostic() + { + var source = @" +public int Foo(int @a) +{ + return a; +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task UsedParameterUsedWithVerbatimIdentifierDoesNotCreateDiagnostic() + { + var source = @" +public int Foo(int a) +{ + return @a; +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task UsedParameterWithVerbatimIdentifierUsedWithVerbatimIdentifierDoesNotCreateDiagnostic() + { + var source = @" +public int Foo(int @a) +{ + return @a; +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task MethodWithoutStatementsCreatesDiagnostic() { From 5c2fb201fb4d1a2013c5cde2cbe6d307c4a101a3 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 27 Mar 2016 21:30:03 -0300 Subject: [PATCH 025/234] Enable to change to ternary with primitive numeric types Fixes #748 Also fixes for type Object --- .../Extensions/CSharpAnalyzerExtensions.cs | 148 +++++++++++++++++- .../Style/TernaryOperatorCodeFixProvider.cs | 10 +- .../Style/TernaryOperatorTests.cs | 123 +++++++++++++++ 3 files changed, 279 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 095b7991c..818a5b276 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -644,7 +644,7 @@ private static InitializerState DoesBlockContainCertainInitializer(this IEnumera var ifResult = ifStatement.Statement.DoesBlockContainCertainInitializer(context, symbol); if (ifStatement.Else != null) { - var elseResult = ifStatement.Else.Statement .DoesBlockContainCertainInitializer(context, symbol); + var elseResult = ifStatement.Else.Statement.DoesBlockContainCertainInitializer(context, symbol); if (ifResult == InitializerState.Initializer && elseResult == InitializerState.Initializer) currentState = InitializerState.Initializer; @@ -722,5 +722,151 @@ public static TypeDeclarationSyntax WithMembers(this TypeDeclarationSyntax typeD throw new NotSupportedException(); } } + + /// + /// According to the C# Language Spec, item 6.4 + /// See online. + /// + /// The type to convert from + /// The type to convert to + public static bool HasImplicitNumericConversion(this ITypeSymbol from, ITypeSymbol to) + { + if (from == null || to == null) return false; + switch (from.SpecialType) + { + case SpecialType.System_SByte: + switch (to.SpecialType) + { + case SpecialType.System_SByte: + case SpecialType.System_Int16: + case SpecialType.System_Int32: + case SpecialType.System_Int64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_Byte: + switch (to.SpecialType) + { + case SpecialType.System_Byte: + case SpecialType.System_Int16: + case SpecialType.System_UInt16: + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_Int16: + switch (to.SpecialType) + { + case SpecialType.System_Int16: + case SpecialType.System_Int32: + case SpecialType.System_Int64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_UInt16: + switch (to.SpecialType) + { + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_Int32: + switch (to.SpecialType) + { + case SpecialType.System_Int32: + case SpecialType.System_Int64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_UInt32: + switch (to.SpecialType) + { + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_Int64: + switch (to.SpecialType) + { + case SpecialType.System_Int64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_UInt64: + switch (to.SpecialType) + { + case SpecialType.System_UInt64: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_Char: + switch (to.SpecialType) + { + case SpecialType.System_UInt16: + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Char: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + case SpecialType.System_Single: + switch (to.SpecialType) + { + case SpecialType.System_Single: + case SpecialType.System_Double: + return true; + default: + return false; + } + default: + return false; + } + } } } diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index cae303ff2..97ebd2e3f 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -135,13 +135,20 @@ private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionS { falseExpression = elseExpression; } - if (!isNullable && !ifType.CanBeAssignedTo(elseType) || !elseType.CanBeAssignedTo(ifType)) + if (!elseType.HasImplicitNumericConversion(ifType) + && !IsEnumAndZero(ifType, elseExpression) + && !IsEnumAndZero(elseType, ifExpression) + && (!isNullable && !ifType.CanBeAssignedTo(elseType) || !elseType.CanBeAssignedTo(ifType))) trueExpression = CastToBaseType(ifExpression, ifType, elseType, trueExpression); } + private static bool IsEnumAndZero(ITypeSymbol type, ExpressionSyntax expression) => + type?.BaseType?.SpecialType == SpecialType.System_Enum && expression?.ToString() == "0"; + private static ExpressionSyntax CastToBaseType(ExpressionSyntax ifExpression, ITypeSymbol ifType, ITypeSymbol elseType, ExpressionSyntax trueExpression) { var commonBaseType = ifType.GetCommonBaseType(elseType); + if (commonBaseType.Equals(ifType)) return trueExpression; if (commonBaseType != null) trueExpression = SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(commonBaseType.Name).WithAdditionalAnnotations(Simplifier.Annotation), ifExpression); return trueExpression; @@ -152,6 +159,7 @@ private static bool CanBeAssignedTo(this ITypeSymbol type, ITypeSymbol possibleB if (type == null || possibleBaseType == null) return true; if (type.Kind == SymbolKind.ErrorType || possibleBaseType.Kind == SymbolKind.ErrorType) return true; if (type == null || possibleBaseType == null) return true; + if (type.SpecialType == SpecialType.System_Object) return true; var baseType = type; while (baseType != null && baseType.SpecialType != SpecialType.System_Object) { diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 73ca6e47c..946cc60f1 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -406,6 +406,129 @@ class TypeName await VerifyCSharpFixAsync(source, fixtest, allowNewCompilerDiagnostics: true); } + [Fact] + public async Task FixWhenThereIsNumericImplicitConversion() + { + var source = @" +static double OnReturn() +{ + var condition = true; + double aDouble = 2; + var bInteger = 3; + if (condition) + return aDouble; + else + return bInteger; +}".WrapInCSharpClass(); + var fixtest = @" +static double OnReturn() +{ + var condition = true; + double aDouble = 2; + var bInteger = 3; + return condition ? aDouble : bInteger; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenThereIsImplicitConversionWithZeroAndEnum() + { + var source = @" +enum FooBar +{ + one, two +} +static FooBar OnReturn() +{ + var condition = true; + var fooBar = FooBar.one; + if (condition) + return 0; + else + return fooBar; +}".WrapInCSharpClass(); + var fixtest = @" +enum FooBar +{ + one, two +} +static FooBar OnReturn() +{ + var condition = true; + var fooBar = FooBar.one; + return condition ? 0 : fooBar; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenThereIsImplicitConversionWithEnumAndZero() + { + var source = @" +enum FooBar +{ + one, two +} +static FooBar OnReturn() +{ + var condition = true; + var fooBar = FooBar.one; + if (condition) + return fooBar; + else + return 0; +}".WrapInCSharpClass(); + var fixtest = @" +enum FooBar +{ + one, two +} +static FooBar OnReturn() +{ + var condition = true; + var fooBar = FooBar.one; + return condition ? fooBar : 0; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningAnObject() + { + var source = @" +static object OnReturn() +{ + var condition = true; + var aInt = 2; + var anObj = new object(); + if (condition) + return anObj; + else + return aInt; +}".WrapInCSharpClass(); + var fixtest = @" +static object OnReturn() +{ + var condition = true; + var aInt = 2; + var anObj = new object(); + return condition ? anObj : aInt; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + static object OnReturn() + { + var condition = true; + var aInt = 2; + var anObj = new object(); + if (condition) + return anObj; + else + return aInt; + } + [Fact] public async Task WhenUsingIfAndElseWithDirectReturnChangeToTernaryFixAll() { From 4d0bac116d4055288b0632b53bbf6b7fc62f98ef Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 27 Mar 2016 21:32:52 -0300 Subject: [PATCH 026/234] Pass exit code 1 to nodemon always Nodemon fails with some exit codes, this way we avoid that. --- runTestsCS.ps1 | 4 ++-- runTestsVB.ps1 | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runTestsCS.ps1 b/runTestsCS.ps1 index bc640573f..2131ad77c 100644 --- a/runTestsCS.ps1 +++ b/runTestsCS.ps1 @@ -24,7 +24,7 @@ If ($testClass) { } If ($testClass) { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass || exit 1" } Else { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" || exit 1" } \ No newline at end of file diff --git a/runTestsVB.ps1 b/runTestsVB.ps1 index d2fe0644e..2da22c936 100644 --- a/runTestsVB.ps1 +++ b/runTestsVB.ps1 @@ -24,7 +24,7 @@ If ($testClass) { } If ($testClass) { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass" + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" -class $testClass || exit 1" } Else { - nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`"" -} \ No newline at end of file + nodemon --watch $testDllFullFileName --exec "`"$xunitConsole`" `"$testDllFullFileName`" || exit 1" +} From f18dfe8d56af89ae52ffb19d6ec54110ad7b9de6 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 28 Mar 2016 23:45:30 -0300 Subject: [PATCH 027/234] Respect precendence rules when nesting if statements Closes #740 Fixing for Logical OR, Conditional and Coalescing. --- .../MergeNestedIfCodeFixProvider.cs | 5 +- .../Refactoring/MergeNestedIfTest.cs | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Refactoring/MergeNestedIfCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/MergeNestedIfCodeFixProvider.cs index 872ca8a8b..ec24113a7 100644 --- a/src/CSharp/CodeCracker/Refactoring/MergeNestedIfCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/MergeNestedIfCodeFixProvider.cs @@ -40,8 +40,11 @@ private async static Task MergeIfsAsync(Document document, Location di private static SyntaxNode MergeIfs(IfStatementSyntax ifStatement, SyntaxNode root) { var nestedIf = (IfStatementSyntax)ifStatement.Statement.GetSingleStatementFromPossibleBlock(); + var nestedCondition = nestedIf.Condition; + if (nestedCondition.IsAnyKind(SyntaxKind.LogicalOrExpression, SyntaxKind.ConditionalExpression, SyntaxKind.CoalesceExpression)) + nestedCondition = SyntaxFactory.ParenthesizedExpression(nestedCondition); var newIf = ifStatement - .WithCondition(SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, ifStatement.Condition, nestedIf.Condition)) + .WithCondition(SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, ifStatement.Condition, nestedCondition)) .WithStatement(nestedIf.Statement) .WithLeadingTrivia(ifStatement.GetLeadingTrivia().AddRange(nestedIf.GetLeadingTrivia())) .WithAdditionalAnnotations(Formatter.Annotation); diff --git a/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs b/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs index 3adee8668..1bcda1b72 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs @@ -185,5 +185,70 @@ public async Task IfWithoutBlockWithNestedIfWithoutBlockFixed() var a = 1;//comment2".WrapInCSharpMethod(); await VerifyCSharpFixAsync(test, fixtest); } + + [Fact] + public async Task FixAddsParenthesisWhenSecondConditionHasLogicalORExpression() + { + var test = @" +var conditionA = false; +var conditionB = false; +var conditionC = false; +if (conditionA) + if (conditionB || conditionC) + System.Console.WriteLine(); +".WrapInCSharpMethod(); + var fixtest = @" +var conditionA = false; +var conditionB = false; +var conditionC = false; +if (conditionA && (conditionB || conditionC)) + System.Console.WriteLine(); +".WrapInCSharpMethod(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task FixAddsParenthesisWhenSecondConditionHasConditionalExpression() + { + var test = @" +var conditionA = false; +var conditionB = false; +var conditionC = false; +var conditionD = false; +if (conditionA) + if (conditionB ? conditionC : conditionD) + System.Console.WriteLine(); +".WrapInCSharpMethod(); + var fixtest = @" +var conditionA = false; +var conditionB = false; +var conditionC = false; +var conditionD = false; +if (conditionA && (conditionB ? conditionC : conditionD)) + System.Console.WriteLine(); +".WrapInCSharpMethod(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task FixAddsParenthesisWhenSecondConditionHasCoalescingExpression() + { + var test = @" +var conditionA = false; +bool? conditionB = false; +var conditionC = false; +if (conditionA) + if (conditionB ?? conditionC) + System.Console.WriteLine(); +".WrapInCSharpMethod(); + var fixtest = @" +var conditionA = false; +bool? conditionB = false; +var conditionC = false; +if (conditionA && (conditionB ?? conditionC)) + System.Console.WriteLine(); +".WrapInCSharpMethod(); + await VerifyCSharpFixAsync(test, fixtest); + } } } \ No newline at end of file From 76f893baf3ceec9ba6896ae808f4561b5f486baa Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 29 Mar 2016 00:18:00 -0300 Subject: [PATCH 028/234] Skip removing Where method when it is called with indexer Closes #752 --- .../RemoveWhereWhenItIsPossibleAnalyzer.cs | 38 +++++++++---------- .../RemoveWhereWhenItIsPossibleTests.cs | 19 ++++++---- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs index 6ddf3bb23..aa7fbda5e 100644 --- a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs @@ -46,40 +46,36 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; var whereInvoke = (InvocationExpressionSyntax)context.Node; - if (GetNameOfTheInvokedMethod(whereInvoke) != "Where") return; + var nameOfWhereInvoke = GetNameOfTheInvokedMethod(whereInvoke); + if (nameOfWhereInvoke?.ToString() != "Where") return; + if (ArgumentsDoNotMatch(whereInvoke)) return; var nextMethodInvoke = whereInvoke.Parent. FirstAncestorOrSelf(); + if (nextMethodInvoke == null) return; - var candidate = GetNameOfTheInvokedMethod(nextMethodInvoke); + var candidate = GetNameOfTheInvokedMethod(nextMethodInvoke)?.ToString(); if (!supportedMethods.Contains(candidate)) return; if (nextMethodInvoke.ArgumentList.Arguments.Any()) return; var properties = new Dictionary { { "methodName", candidate } }.ToImmutableDictionary(); - var diagnostic = Diagnostic.Create(Rule, GetNameExpressionOfTheInvokedMethod(whereInvoke).GetLocation(), properties, candidate); + var diagnostic = Diagnostic.Create(Rule, nameOfWhereInvoke.GetLocation(), properties, candidate); context.ReportDiagnostic(diagnostic); } - internal static string GetNameOfTheInvokedMethod(InvocationExpressionSyntax invoke) + private static bool ArgumentsDoNotMatch(InvocationExpressionSyntax whereInvoke) { - if (invoke == null) return null; - - var memberAccess = invoke.ChildNodes() - .OfType() - .FirstOrDefault(); - - return GetNameExpressionOfTheInvokedMethod(invoke)?.ToString(); + var arguments = whereInvoke.ArgumentList.Arguments; + if (arguments.Count != 1) return true; + var expression = arguments.First()?.Expression; + if (expression == null) return true; + if (expression is SimpleLambdaExpressionSyntax) return false; + var parenthesizedLambda = expression as ParenthesizedLambdaExpressionSyntax; + if (parenthesizedLambda == null) return true; + return parenthesizedLambda.ParameterList.Parameters.Count != 1; } - internal static SimpleNameSyntax GetNameExpressionOfTheInvokedMethod(InvocationExpressionSyntax invoke) - { - if (invoke == null) return null; - - var memberAccess = invoke.ChildNodes() - .OfType() - .FirstOrDefault(); - - return memberAccess?.Name; - } + private static SimpleNameSyntax GetNameOfTheInvokedMethod(InvocationExpressionSyntax invoke) => + invoke.ChildNodes().OfType().FirstOrDefault()?.Name; } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs index dc64b6c7b..c6e4b622a 100644 --- a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs @@ -69,11 +69,19 @@ public async Task DoSomething() } } }"; - await VerifyCSharpHasNoDiagnosticsAsync(test); - } + [Fact] + public async Task DoNotCreateDiagnosticWhenWhereUsesIndexer() + { + var test = @" +var first = Enumerable.Range(1, 10).ToList(); +var second = Enumerable.Range(1, 10); +var isNotMatch = second.Where((t, i) => first[i] != t).Any(); +".WrapInCSharpMethod(usings: "using System.Linq;"); + await VerifyCSharpHasNoDiagnosticsAsync(test); + } [Theory] [InlineData("First")] @@ -96,11 +104,10 @@ public class Foo public async Task DoSomething() { var a = new int[10]; - var f = a.Where(item => item > 10)." + method + @"(); + var f = a.Where((item) => item > 10)." + method + @"(); } } }"; - var expected = @" using System.Linq; @@ -111,13 +118,11 @@ public class Foo public async Task DoSomething() { var a = new int[10]; - var f = a." + method + @"(item => item > 10); + var f = a." + method + @"((item) => item > 10); } } }"; - await VerifyCSharpFixAsync(test, expected); - } [Theory] From 2cdd64299b578c37efbcb1af099e6735c6b1aa46 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 29 Mar 2016 01:08:01 -0300 Subject: [PATCH 029/234] Enable attributes when ignoring private methods in VB Fixes #744 Also, fixes on C# when qualified names were not verified Also, check for entry points in VB (already worked, only tests) --- .../RemovePrivateMethodNeverUsedAnalyzer.cs | 12 ++++- .../RemovePrivateMethodNeverUsedAnalyzer.vb | 27 +++++++++++ ...emovePrivateMethodNeverUsedAnalyzerTest.cs | 1 + ...emovePrivateMethodNeverUsedAnalyzerTest.vb | 47 +++++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs index 335173ed5..40b86f79d 100644 --- a/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs @@ -58,7 +58,17 @@ private static bool IsMethodAttributeAnException(MethodDeclarationSyntax methodD foreach (var attribute in attributeList.Attributes) { var identifierName = attribute.Name as IdentifierNameSyntax; - var nameText = identifierName?.Identifier.Text; + string nameText = null; + if (identifierName != null) + { + nameText = identifierName?.Identifier.Text; + } + else + { + var qualifiedName = attribute.Name as QualifiedNameSyntax; + if (qualifiedName != null) + nameText = qualifiedName.Right?.Identifier.Text; + } if (nameText == null) continue; if (IsExcludedAttributeName(nameText)) return true; } diff --git a/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb b/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb index c273ef808..e1ecd9068 100644 --- a/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb @@ -38,12 +38,39 @@ Namespace Usage Dim methodStatement = DirectCast(context.Node, MethodStatementSyntax) If methodStatement.HandlesClause IsNot Nothing Then Exit Sub If Not methodStatement.Modifiers.Any(Function(a) a.ValueText = SyntaxFactory.Token(SyntaxKind.PrivateKeyword).ValueText) Then Exit Sub + If (IsMethodAttributeAnException(methodStatement)) Then Return If IsMethodUsed(methodStatement, context.SemanticModel) Then Exit Sub Dim props = New Dictionary(Of String, String) From {{"identifier", methodStatement.Identifier.Text}}.ToImmutableDictionary() Dim diag = Diagnostic.Create(Rule, methodStatement.GetLocation(), props) context.ReportDiagnostic(diag) End Sub + Private Function IsMethodAttributeAnException(methodStatement As MethodStatementSyntax) As Boolean + For Each attributeList In methodStatement.AttributeLists + For Each attribute In attributeList.Attributes + Dim identifierName = TryCast(attribute.Name, IdentifierNameSyntax) + Dim nameText As String = Nothing + If (identifierName IsNot Nothing) Then + nameText = identifierName?.Identifier.Text + Else + Dim qualifiedName = TryCast(attribute.Name, QualifiedNameSyntax) + If (qualifiedName IsNot Nothing) Then + nameText = qualifiedName.Right?.Identifier.Text + End If + End If + If (nameText Is Nothing) Then Continue For + If (IsExcludedAttributeName(nameText)) Then Return True + Next + Next + Return False + End Function + + Private Shared ReadOnly excludedAttributeNames As String() = {"Fact", "ContractInvariantMethod", "DataMember"} + + Private Shared Function IsExcludedAttributeName(attributeName As String) As Boolean + Return excludedAttributeNames.Contains(attributeName) + End Function + Private Function IsMethodUsed(methodTarget As MethodStatementSyntax, semanticModel As SemanticModel) As Boolean Dim typeDeclaration = TryCast(methodTarget.Parent.Parent, ClassBlockSyntax) If typeDeclaration Is Nothing Then Return True diff --git a/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs b/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs index c866a17b0..abc0c6e97 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs @@ -9,6 +9,7 @@ public class RemovePrivateMethodNeverUsedAnalyzerTest : CodeFixVerifier + + + + + Public Async Function DoesNotGenerateDiagnosticsWhenMethodAttributeIsAnException(value As String) As Task + Dim source = " +Class Foo + <" + value + "> + Private Sub PrivateFoo() + End Sub +End Class" + Await VerifyBasicHasNoDiagnosticsAsync(source) + End Function + + + Public Async Function MainMethodEntryPointReturningVoidDoesNotCreateDiagnostic() As Task + Const test = " +Module Foo + Sub Main(args as String()) + End Sub +End Module" + Await VerifyBasicHasNoDiagnosticsAsync(test) + End Function + + + Public Async Function MainMethodEntryPointReturningIntegerDoesNotCreateDiagnostic() As Task + Const test = " +Module Foo + Function Main(args as String()) as Integer + Return 0 + End Function +End Module" + Await VerifyBasicHasNoDiagnosticsAsync(test) + End Function + + + Public Async Function MainMethodEntryPointWithoutParameterDoesNotCreateDiagnostic() As Task + Const test = " +Module Foo + Function Main() as Integer + Return 0 + End Function +End Module" + Await VerifyBasicHasNoDiagnosticsAsync(test) + End Function + Public Async Function DoesNotGenerateDiagnostics() As Task Const test = " From e83d55b1535f52c958d630d90d4529a1bde34b98 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 31 Mar 2016 01:00:36 -0300 Subject: [PATCH 030/234] Enable to change to ternary with primitive numeric types Fixes #745 --- .../Extensions/VBAnalyzerExtensions.vb | 20 ++++++- .../Style/TernaryOperatorCodeFixProviders.vb | 3 +- .../Helpers/Extensions.cs | 14 +++++ .../Style/TernaryOperatorTests.vb | 53 +++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Extensions/VBAnalyzerExtensions.vb b/src/VisualBasic/CodeCracker/Extensions/VBAnalyzerExtensions.vb index 9b3ed1894..d7fe23787 100644 --- a/src/VisualBasic/CodeCracker/Extensions/VBAnalyzerExtensions.vb +++ b/src/VisualBasic/CodeCracker/Extensions/VBAnalyzerExtensions.vb @@ -42,10 +42,28 @@ Public Module VBAnalyzerExtensions Public Function ConvertToBaseType(source As ExpressionSyntax, sourceType As ITypeSymbol, targetType As ITypeSymbol) As ExpressionSyntax - If targetType?.OriginalDefinition.SpecialType = SpecialType.System_Nullable_T Then Return source + If (sourceType?.IsNumeric() AndAlso targetType?.IsNumeric()) OrElse + (sourceType?.BaseType?.SpecialType = SpecialType.System_Enum AndAlso targetType?.IsNumeric()) OrElse + (targetType?.OriginalDefinition.SpecialType = SpecialType.System_Nullable_T) Then Return source Return If(sourceType IsNot Nothing AndAlso sourceType.Name = targetType.Name, source, SyntaxFactory.DirectCastExpression(source.WithoutTrailingTrivia, SyntaxFactory.ParseTypeName(targetType.Name))).WithTrailingTrivia(source.GetTrailingTrivia()) End Function + + Public Function IsNumeric(typeSymbol As ITypeSymbol) As Boolean + Return typeSymbol.SpecialType = SpecialType.System_Byte OrElse + typeSymbol.SpecialType = SpecialType.System_SByte OrElse + typeSymbol.SpecialType = SpecialType.System_Int16 OrElse + typeSymbol.SpecialType = SpecialType.System_UInt16 OrElse + typeSymbol.SpecialType = SpecialType.System_Int16 OrElse + typeSymbol.SpecialType = SpecialType.System_UInt32 OrElse + typeSymbol.SpecialType = SpecialType.System_Int32 OrElse + typeSymbol.SpecialType = SpecialType.System_UInt64 OrElse + typeSymbol.SpecialType = SpecialType.System_Int64 OrElse + typeSymbol.SpecialType = SpecialType.System_Decimal OrElse + typeSymbol.SpecialType = SpecialType.System_Single OrElse + typeSymbol.SpecialType = SpecialType.System_Double + End Function + Public Function EnsureNothingAsType(expression As ExpressionSyntax, semanticModel As SemanticModel, type As ITypeSymbol, typeSyntax As TypeSyntax) As ExpressionSyntax If type?.OriginalDefinition.SpecialType = SpecialType.System_Nullable_T Then diff --git a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb index 11d68892c..4b60a321e 100644 --- a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb +++ b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb @@ -62,7 +62,8 @@ Namespace Style Dim returnStatement = SyntaxFactory.ReturnStatement(ternary). WithLeadingTrivia(leadingTrivia). - WithTrailingTrivia(trailingTrivia) + WithTrailingTrivia(trailingTrivia). + WithAdditionalAnnotations(Formatter.Annotation) Dim newRoot = root.ReplaceNode(ifBlock, returnStatement) Dim newDocument = document.WithSyntaxRoot(newRoot) diff --git a/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs b/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs index 514ab1e6b..082843818 100644 --- a/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs +++ b/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs @@ -32,6 +32,20 @@ class {typeName} }} }}"; } + + public static string WrapInVBClass(this string code, + string typeName = "TypeName", + string imports = "") + { + return $@" +Imports System{imports} +Namespace ConsoleApplication1 + Class {typeName} + {code} + End Class +End Namespace"; + } + public static string WrapInVBMethod(this string code, bool isAsync = false, string typeName = "TypeName", diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index b363d18ba..80a039a2a 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -5,6 +5,7 @@ Namespace Style Public Class TernaryOperatorWithAssignmentTests Inherits CodeFixVerifier(Of TernaryOperatorAnalyzer, TernaryOperatorWithAssignmentCodeFixProvider) + Public Async Function WhenUsingIfWithoutElseAnalyzerDoesNotCreateDiagnostic() As Task Const sourceWithoutElse = " Namespace ConsoleApplication1 @@ -711,6 +712,58 @@ End Namespace" Await VerifyBasicFixAllAsync(New String() {sourceReturn, sourceReturn.Replace("MyType", "MyType1")}, New String() {fix, fix.Replace("MyType", "MyType1")}) End Function + + Public Async Function FixWhenThereIsNumericImplicitConversion() As Task + Dim source = " +Function OnReturn() As Double + Dim condition = True + Dim aDouble As Double = 2 + Dim bInteger = 3 + If condition Then + Return aDouble + Else + Return bInteger + End If +End Function".WrapInVBClass() + Dim fix = " +Function OnReturn() As Double + Dim condition = True + Dim aDouble As Double = 2 + Dim bInteger = 3 + Return If(condition, aDouble, bInteger) +End Function".WrapInVBClass() + Await VerifyBasicFixAsync(source, fix, formatBeforeCompare:=True) + End Function + + + Public Async Function FixWhenThereIsEnumImplicitConversionToNumeric() As Task + Dim source = " +Enum Values + Value +End Enum +Function OnReturn() As Double + Dim condition = True + Dim anEnum As Values = Values.Value + Dim bInteger = 3 + If condition Then + Return anEnum + Else + Return bInteger + End If +End Function".WrapInVBClass() + Dim fix = " +Enum Values + Value +End Enum +Function OnReturn() As Double + Dim condition = True + Dim anEnum As Values = Values.Value + Dim bInteger = 3 + Return If(condition, anEnum, bInteger) +End Function".WrapInVBClass() + Await VerifyBasicFixAsync(source, fix, formatBeforeCompare:=True) + End Function + Public Async Function FixCanWorkWithCommentsOnIf() As Task Const source = " From 4ac0f32700ee4cc1fbaa651f6492b8e8cd702111 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Wed, 30 Mar 2016 23:01:27 -0300 Subject: [PATCH 031/234] Can copy evento to variable without crashing when inside a statement Fixes #735 --- ...ventToVariableBeforeFireCodeFixProvider.cs | 18 +++--- .../Extensions/CSharpAnalyzerExtensions.cs | 11 +++- .../CopyEventToVariableBeforeFireTests.cs | 58 +++++++++++++++++++ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs index 88380df5b..7dd79aa7c 100644 --- a/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs @@ -30,12 +30,13 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) return Task.FromResult(0); } - private async static Task CreateVariableAsync(Document document, Diagnostic diagnostic, CancellationToken ct) + private async static Task CreateVariableAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { - var root = await document.GetSyntaxRootAsync(ct).ConfigureAwait(false); + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var sourceSpan = diagnostic.Location.SourceSpan; var invocation = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - const string handlerName = "handler"; + var semanticModel = await document.GetSemanticModelAsync(cancellationToken); + var handlerName = semanticModel.FindAvailableIdentifierName(sourceSpan.Start, "handler"); var variable = SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration( @@ -49,18 +50,17 @@ private async static Task CreateVariableAsync(Document document, Diagn SyntaxFactory.EqualsValueClause(invocation.Expression.WithoutLeadingTrivia().WithoutTrailingTrivia())) }))) .WithLeadingTrivia(invocation.Parent.GetLeadingTrivia()); + var statement = invocation.Expression.FirstAncestorOrSelfThatIsAStatement(); + var newStatement = statement.ReplaceNode(invocation.Expression, SyntaxFactory.IdentifierName(handlerName)); var newInvocation = SyntaxFactory.IfStatement( SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, SyntaxFactory.IdentifierName(handlerName), SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)), - SyntaxFactory.ExpressionStatement( - SyntaxFactory.InvocationExpression( - SyntaxFactory.IdentifierName(handlerName), - invocation.ArgumentList))) + newStatement) .WithTrailingTrivia(invocation.Parent.GetTrailingTrivia()); - var oldNode = invocation.Parent; - var newNode = invocation.Parent.WithAdditionalAnnotations(new SyntaxAnnotation(SyntaxAnnotatinKind)); + var oldNode = statement; + var newNode = newStatement.WithAdditionalAnnotations(new SyntaxAnnotation(SyntaxAnnotatinKind)); if (oldNode.Parent.IsEmbeddedStatementOwner()) newNode = SyntaxFactory.Block((StatementSyntax)newNode); var newRoot = root.ReplaceNode(oldNode, newNode); diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 818a5b276..358b3fc6c 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -868,5 +868,14 @@ public static bool HasImplicitNumericConversion(this ITypeSymbol from, ITypeSymb return false; } } + + public static string FindAvailableIdentifierName(this SemanticModel semanticModel, int position, string baseName) + { + var name = baseName; + var inscrementer = 1; + while (semanticModel.LookupSymbols(position, name: name).Any()) + name = baseName + inscrementer++; + return name; + } } -} +} \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs b/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs index 706874d4a..e681b3057 100644 --- a/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs @@ -765,5 +765,63 @@ public int FuncCalc(int p1, int p2) }"; await VerifyCSharpHasNoDiagnosticsAsync(test); } + + [Fact] + public async void FixWhenInsideExpression() + { + var code = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + var fix = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + var handler = AllowInteraction; + if (handler != null) + if (!handler("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(code, fix); + } + + [Fact] + public async void FixWhenInsideExpressionAndNameAlreadyExists() + { + var code = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + var handler = 1; + if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + var fix = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + var handler = 1; + var handler1 = AllowInteraction; + if (handler1 != null) + if (!handler1("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(code, fix); + } } } \ No newline at end of file From c3866fffc57dcab7b72e909aad625b176bb6753d Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 1 Apr 2016 17:29:24 -0300 Subject: [PATCH 032/234] Detect dispose when using elvis operator on CC0022 Closes #761 --- .../DisposableVariableNotDisposedAnalyzer.cs | 34 ++++++++++++++----- .../DisposableVariableNotDisposedTests.cs | 10 ++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index 9901b2114..e53f40891 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -176,17 +176,35 @@ private static bool IsCorrectDispose(ExpressionStatementSyntax expressionStateme { if (expressionStatement == null) return false; var invocation = expressionStatement.Expression as InvocationExpressionSyntax; - if (invocation?.ArgumentList.Arguments.Any() ?? true) return false; - var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; - if (memberAccess == null) return false; + ExpressionSyntax expressionAccessed; + IdentifierNameSyntax memberAccessed; + if (invocation == null) + { + var conditionalAccessExpression = expressionStatement.Expression as ConditionalAccessExpressionSyntax; + if (conditionalAccessExpression == null) return false; + invocation = conditionalAccessExpression.WhenNotNull as InvocationExpressionSyntax; + var memberBinding = invocation?.Expression as MemberBindingExpressionSyntax; + if (memberBinding == null) return false; + expressionAccessed = conditionalAccessExpression.Expression; + memberAccessed = memberBinding.Name as IdentifierNameSyntax; + } + else + { + var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; + if (memberAccess == null) return false; + expressionAccessed = memberAccess.Expression; + memberAccessed = memberAccess.Name as IdentifierNameSyntax; + } + if (memberAccessed == null) return false; + if (invocation.ArgumentList.Arguments.Any()) return false; ISymbol memberSymbol; - if (memberAccess.Expression.IsKind(SyntaxKind.IdentifierName)) + if (expressionAccessed.IsKind(SyntaxKind.IdentifierName)) { - memberSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol; + memberSymbol = semanticModel.GetSymbolInfo(expressionAccessed).Symbol; } - else if (memberAccess.Expression.IsKind(SyntaxKind.ParenthesizedExpression)) + else if (expressionAccessed is ParenthesizedExpressionSyntax) { - var parenthesizedExpression = (ParenthesizedExpressionSyntax)memberAccess.Expression; + var parenthesizedExpression = (ParenthesizedExpressionSyntax)expressionAccessed; var cast = parenthesizedExpression.Expression as CastExpressionSyntax; if (cast == null) return false; var catTypeSymbol = semanticModel.GetTypeInfo(cast.Type).Type; @@ -195,8 +213,6 @@ private static bool IsCorrectDispose(ExpressionStatementSyntax expressionStateme } else return false; if (memberSymbol == null || !memberSymbol.Equals(identitySymbol)) return false; - var memberAccessed = memberAccess.Name as IdentifierNameSyntax; - if (memberAccessed == null) return false; if (memberAccessed.Identifier.Text != "Dispose" || memberAccessed.Arity != 0) return false; var methodSymbol = semanticModel.GetSymbolInfo(memberAccessed).Symbol as IMethodSymbol; if (methodSymbol == null) return false; diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index ba53e0a9b..a07c13405 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -72,6 +72,16 @@ public async Task FixADisposableDeclarationWithoutDisposeWithParenthese() await VerifyCSharpFixAsync(source, fixtest); } + [Fact] + public async Task IgnoreWhenDisposedWithElvisOperator() + { + var source = @" +var m = new System.IO.MemoryStream(); +m?.Dispose(); +".WrapInCSharpMethod(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task IgnoresDisposableObjectsCreatedDirectParentIsNotAnUsingStatement() { From fe0fd387a6bdfc20ee31ca50da388c1f06f18254 Mon Sep 17 00:00:00 2001 From: carloscds Date: Sat, 2 Apr 2016 19:56:07 -0300 Subject: [PATCH 033/234] Fix #733 --- .../CodeCracker/Usage/UnusedParametersAnalyzer.vb | 1 + .../CodeCracker.Test/Usage/UnusedParametersTests.vb | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/VisualBasic/CodeCracker/Usage/UnusedParametersAnalyzer.vb b/src/VisualBasic/CodeCracker/Usage/UnusedParametersAnalyzer.vb index 5e338294a..eccfc6a13 100644 --- a/src/VisualBasic/CodeCracker/Usage/UnusedParametersAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Usage/UnusedParametersAnalyzer.vb @@ -65,6 +65,7 @@ You should delete the parameter in such cases." Private Shared Function IsCandidateForRemoval(methodOrConstructor As MethodBlockBaseSyntax, semanticModel As SemanticModel) As Boolean If methodOrConstructor.BlockStatement.Modifiers.Any(Function(m) m.ValueText = "Partial" OrElse m.ValueText = "Overrides") OrElse Not methodOrConstructor.BlockStatement.ParameterList?.Parameters.Any() Then Return False + If methodOrConstructor.HasAttributeOnAncestorOrSelf("DllImport") Then Return False Dim method = TryCast(methodOrConstructor, MethodBlockSyntax) If method IsNot Nothing Then diff --git a/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb index f8e0e5bc9..e6c044c9c 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb @@ -464,6 +464,19 @@ End Class Await VerifyBasicDiagnosticAsync(source, CreateDiagnosticResult("out2", 3, 77)) End Function + + Public Async Function CallWithDllImport() As Task + Const source = " +Imports System.Runtime.InteropServices +Class Base + + Private Shared Function y(ByRef message As IntPtr) As Integer + End Function +End Class +" + Await VerifyBasicHasNoDiagnosticsAsync(source) + End Function + Public Async Function CallWithRefAndEnumerableDoesNotCreateDiagnostic() As Task Const source = " From 742b2bee0a00be9746eb0c80a7bc06e69c24df68 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 2 Apr 2016 22:35:56 -0300 Subject: [PATCH 034/234] Update XmlDocumentation to raise 2 different diagnostic ids Use CC0090 for incorrect params (params that exist in the docs but not on code) and CC0097 for missing parameters (params that exist on code, but not on docs). Make 90 an Info, and 97 a Warning. Closes #488 --- src/CSharp/CodeCracker/CodeCracker.csproj | 4 ++-- .../XmlDocumentationAnalyzer.cs | 23 ++++++++++++------- .../XmlDocumentationCodeFixProvider.cs | 2 -- ...entationMissingInCSharpCodeFixProvider.cs} | 14 ++++++----- ...cumentationMissingInXmlCodeFixProvider.cs} | 22 +++++++++--------- src/Common/CodeCracker.Common/DiagnosticId.cs | 3 ++- .../Maintainability/XmlDocumentationTests.cs | 12 +++++----- 7 files changed, 44 insertions(+), 36 deletions(-) rename src/CSharp/CodeCracker/Maintainability/{XmlDocumentationRemoveNonExistentParametersCodeFixProvider.cs => XmlDocumentationMissingInCSharpCodeFixProvider.cs} (77%) rename src/CSharp/CodeCracker/Maintainability/{XmlDocumentationCreateMissingParametersCodeFixProvider.cs => XmlDocumentationMissingInXmlCodeFixProvider.cs} (89%) diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 3a914dbb4..c7701d03d 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -75,8 +75,8 @@ - - + + diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs index f4da96669..5f987fddb 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationAnalyzer.cs @@ -14,16 +14,25 @@ public sealed class XmlDocumentationAnalyzer : DiagnosticAnalyzer { internal static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.XmlDocumentationAnalyzer_Title), Resources.ResourceManager, typeof(Resources)); - internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( - DiagnosticId.XmlDocumentation.ToDiagnosticId(), + internal static readonly DiagnosticDescriptor RuleMissingInCSharp = new DiagnosticDescriptor( + DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId(), + Title, + Title, + SupportedCategories.Maintainability, + DiagnosticSeverity.Info, + isEnabledByDefault: true, + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.XmlDocumentation_MissingInCSharp)); + + internal static readonly DiagnosticDescriptor RuleMissingInXml = new DiagnosticDescriptor( + DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId(), Title, Title, SupportedCategories.Maintainability, DiagnosticSeverity.Warning, isEnabledByDefault: true, - helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.XmlDocumentation)); + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.XmlDocumentation_MissingInXml)); - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(RuleMissingInCSharp, RuleMissingInXml); public override void Initialize(AnalysisContext context) => context.RegisterSyntaxNodeAction(Analyzer, SyntaxKind.SingleLineDocumentationCommentTrivia); @@ -55,15 +64,13 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (parameterWithDocParameter.Any(p => p.Parameter == null)) { - var properties = new Dictionary { ["kind"] = "nonexistentParam" }.ToImmutableDictionary(); - var diagnostic = Diagnostic.Create(Rule, documentationNode.GetLocation(), properties); + var diagnostic = Diagnostic.Create(RuleMissingInCSharp, documentationNode.GetLocation()); context.ReportDiagnostic(diagnostic); } if (parameterWithDocParameter.Any(p => p.DocParameter == null)) { - var properties = new Dictionary { ["kind"] = "missingDoc" }.ToImmutableDictionary(); - var diagnostic = Diagnostic.Create(Rule, documentationNode.GetLocation(), properties); + var diagnostic = Diagnostic.Create(RuleMissingInXml, documentationNode.GetLocation()); context.ReportDiagnostic(diagnostic); } } diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationCodeFixProvider.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationCodeFixProvider.cs index 06e7b5cc7..60cf4f0aa 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationCodeFixProvider.cs @@ -12,8 +12,6 @@ namespace CodeCracker.CSharp.Maintainability { public abstract class XmlDocumentationCodeFixProvider : CodeFixProvider { - public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.XmlDocumentation.ToDiagnosticId()); - public abstract SyntaxNode FixParameters(MethodDeclarationSyntax method, SyntaxNode root); protected async Task FixParametersAsync(Document document, Diagnostic diagnostic, CancellationToken c) diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationRemoveNonExistentParametersCodeFixProvider.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs similarity index 77% rename from src/CSharp/CodeCracker/Maintainability/XmlDocumentationRemoveNonExistentParametersCodeFixProvider.cs rename to src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs index 04e3e3e01..232533605 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationRemoveNonExistentParametersCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs @@ -1,19 +1,22 @@ -using Microsoft.CodeAnalysis; +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Composition; using System.Linq; using System.Threading.Tasks; -using CodeCracker.Properties; namespace CodeCracker.CSharp.Maintainability { [ExportCodeFixProvider(LanguageNames.CSharp, nameof(XmlDocumentationCodeFixProvider)), Shared] - public sealed class XmlDocumentationRemoveNonExistentParametersCodeFixProvider : XmlDocumentationCodeFixProvider + public sealed class XmlDocumentationMissingInCSharpCodeFixProvider : XmlDocumentationCodeFixProvider { + public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId()); + public override SyntaxNode FixParameters(MethodDeclarationSyntax method, SyntaxNode root) { var documentationNode = method.GetLeadingTrivia().Select(x => x.GetStructure()).OfType().First(); @@ -39,9 +42,8 @@ private static IEnumerable GetAllNodesToRemove(IEnumerable FixParametersAsync(context.Document, diagnostic, c)), diagnostic); + context.RegisterCodeFix(CodeAction.Create(Resources.XmlDocumentationRemoveNonExistentParametersCodeFixProvider_Title, c => FixParametersAsync(context.Document, diagnostic, c)), diagnostic); return Task.FromResult(0); } } -} +} \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationCreateMissingParametersCodeFixProvider.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs similarity index 89% rename from src/CSharp/CodeCracker/Maintainability/XmlDocumentationCreateMissingParametersCodeFixProvider.cs rename to src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs index b9012de39..be54bc846 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationCreateMissingParametersCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs @@ -1,19 +1,22 @@ -using System.Composition; -using System.Linq; -using System.Threading.Tasks; -using CodeCracker.Properties; +using CodeCracker.Properties; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading.Tasks; using static Microsoft.CodeAnalysis.CSharp.SyntaxKind; namespace CodeCracker.CSharp.Maintainability { [ExportCodeFixProvider(LanguageNames.CSharp, nameof(XmlDocumentationCodeFixProvider)), Shared] - public sealed class XmlDocumentationCreateMissingParametersCodeFixProvider : XmlDocumentationCodeFixProvider + public sealed class XmlDocumentationMissingInXmlCodeFixProvider : XmlDocumentationCodeFixProvider { + public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId()); + private const string WHITESPACE = @" "; public override SyntaxNode FixParameters(MethodDeclarationSyntax method, SyntaxNode root) @@ -23,7 +26,7 @@ public override SyntaxNode FixParameters(MethodDeclarationSyntax method, SyntaxN var methodParameterWithDocParameter = GetMethodParametersWithDocParameters(method, documentationNode); var newFormation = newDocumentationNode.Content.OfType(); - + var nodesToAdd = methodParameterWithDocParameter.Where(p => p.Item2 == null) .Select(x => CreateParamenterXmlDocumentation(x.Item1.Identifier.ValueText, method.Identifier.ValueText)) .Union(newFormation) @@ -83,11 +86,8 @@ private static SyntaxList CreateXmlAttributes(string paramen public override sealed Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); - if (diagnostic.Properties["kind"] == "missingDoc") - context.RegisterCodeFix(CodeAction.Create(Resources.XmlDocumentationCreateMissingParametersCodeFixProvider_Title, c => FixParametersAsync(context.Document, diagnostic, c)), diagnostic); + context.RegisterCodeFix(CodeAction.Create(Resources.XmlDocumentationCreateMissingParametersCodeFixProvider_Title, c => FixParametersAsync(context.Document, diagnostic, c)), diagnostic); return Task.FromResult(0); } } - - -} +} \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index b3e757224..cad9ad940 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -73,10 +73,11 @@ public enum DiagnosticId UseStringEmpty = 84, UseEmptyString = 88, RemoveRedundantElseClause = 89, - XmlDocumentation = 90, + XmlDocumentation_MissingInCSharp = 90, MakeMethodStatic = 91, ChangeAllToAny = 92, ConsoleWriteLine = 95, + XmlDocumentation_MissingInXml = 97, NameOf_External = 108, StringFormatArgs_ExtraArgs = 111, AlwaysUseVarOnPrimitives = 105, diff --git a/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs b/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs index 83ca47b91..4e060ac36 100644 --- a/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs +++ b/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs @@ -5,7 +5,7 @@ namespace CodeCracker.Test.CSharp.Maintainability { - public class XmlDocumentationAnalyzerTests : CodeFixVerifier + public class XmlDocumentationAnalyzerTests : CodeFixVerifier { [Fact] public async Task IgnoresClassDocs() @@ -112,9 +112,9 @@ protected async static Task GetSortedDiagnosticsFromDocumentsAsync var expected = new DiagnosticResult { - Id = DiagnosticId.XmlDocumentation.ToDiagnosticId(), + Id = DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId(), Message = "You have missing/unexistent parameters in Xml Docs", - Severity = DiagnosticSeverity.Warning, + Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 16) } }; @@ -143,7 +143,7 @@ public static Project CreateProject(string[] sources, out AdhocWorkspace workspa var expected = new DiagnosticResult { - Id = DiagnosticId.XmlDocumentation.ToDiagnosticId(), + Id = DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId(), Message = "You have missing/unexistent parameters in Xml Docs", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 16) } @@ -192,7 +192,7 @@ public int Foo(int value) } } - public class XmlDocumentationRemoveUnexistentParametersCodeFixTests : CodeFixVerifier + public class XmlDocumentationRemoveUnexistentParametersCodeFixTests : CodeFixVerifier { [Fact] public async Task FixRemoveParameterDoc() @@ -278,7 +278,7 @@ protected async static Task GetSortedDiagnosticsFromDocumentsAsync } - public class XmlDocumentationCreateMissingParametersCodeFixTests : CodeFixVerifier + public class XmlDocumentationCreateMissingParametersCodeFixTests : CodeFixVerifier { [Fact] public async Task FixCreateOneParameterDoc() From effcd89592b2c4f1502c4986eb1a2defc61d25b2 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 00:59:34 -0300 Subject: [PATCH 035/234] Unify CC0016 and CC0031 Closes #662 --- src/CSharp/CodeCracker/CodeCracker.csproj | 2 - .../CopyEventToVariableBeforeFireAnalyzer.cs | 54 -- ...ventToVariableBeforeFireCodeFixProvider.cs | 75 -- .../UseInvokeMethodToFireEventAnalyzer.cs | 15 +- ...eInvokeMethodToFireEventCodeFixProvider.cs | 89 +- src/Common/CodeCracker.Common/DiagnosticId.cs | 1 - .../Extensions/AnalyzerExtensions.cs | 2 + .../CodeCracker.Test/CodeCracker.Test.csproj | 1 - .../CopyEventToVariableBeforeFireTests.cs | 827 ------------------ .../Design/UseInvokeMethodToFireEventTests.cs | 622 ++++++++++++- .../Verifiers/CodeFixVerifier.cs | 39 + 11 files changed, 757 insertions(+), 970 deletions(-) delete mode 100644 src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireAnalyzer.cs delete mode 100644 src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs delete mode 100644 test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index c7701d03d..0f1d5e220 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -115,8 +115,6 @@ - - diff --git a/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireAnalyzer.cs b/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireAnalyzer.cs deleted file mode 100644 index 9194eecf2..000000000 --- a/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireAnalyzer.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System; -using System.Collections.Immutable; - -namespace CodeCracker.CSharp.Design -{ - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public class CopyEventToVariableBeforeFireAnalyzer : DiagnosticAnalyzer - { - internal const string Title = "Copy Event To Variable Before Fire"; - internal const string MessageFormat = "Copy the '{0}' event to a variable before firing it."; - internal const string Category = SupportedCategories.Design; - const string Description = "Events should always be checked for null before being invoked.\r\n" - + "As in a multi-threading context it is possible for an event to be unsubscribed between " - + "the moment where it is checked to be non-null and the moment it is raised the event must " - + "be copied to a temporary variable before the check."; - internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( - DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Title, - MessageFormat, - Category, - DiagnosticSeverity.Warning, - true, - description: Description, - helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.CopyEventToVariableBeforeFire)); - - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); - - public override void Initialize(AnalysisContext context) => context.RegisterSyntaxNodeAction(Analyzer, SyntaxKind.InvocationExpression); - - private static void Analyzer(SyntaxNodeAnalysisContext context) - { - if (context.IsGenerated()) return; - var invocation = (InvocationExpressionSyntax)context.Node; - var identifier = invocation.Expression as IdentifierNameSyntax; - if (identifier == null) return; - if (context.Node.Parent.GetType().Name == nameof(ArrowExpressionClauseSyntax)) return; - - var typeInfo = context.SemanticModel.GetTypeInfo(identifier, context.CancellationToken); - - if (typeInfo.ConvertedType?.BaseType == null) return; - - var symbol = context.SemanticModel.GetSymbolInfo(identifier).Symbol; - - if (typeInfo.ConvertedType.BaseType.Name != typeof(MulticastDelegate).Name || - symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.Parameter || symbol.IsReadOnlyAndInitializedForCertain(context)) return; - - context.ReportDiagnostic(Diagnostic.Create(Rule, invocation.GetLocation(), identifier.Identifier.Text)); - } - } -} \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs deleted file mode 100644 index 7dd79aa7c..000000000 --- a/src/CSharp/CodeCracker/Design/CopyEventToVariableBeforeFireCodeFixProvider.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Formatting; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace CodeCracker.CSharp.Design -{ - [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CopyEventToVariableBeforeFireCodeFixProvider)), Shared] - public class CopyEventToVariableBeforeFireCodeFixProvider : CodeFixProvider - { - private const string SyntaxAnnotatinKind = "CC-CopyEvent"; - - public sealed override ImmutableArray FixableDiagnosticIds => - ImmutableArray.Create(DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId()); - - public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - - public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) - { - var diagnostic = context.Diagnostics.First(); - context.RegisterCodeFix( - CodeAction.Create("Copy event reference to a variable", ct => CreateVariableAsync(context.Document, diagnostic, ct), nameof(CopyEventToVariableBeforeFireCodeFixProvider)), diagnostic); - return Task.FromResult(0); - } - - private async static Task CreateVariableAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) - { - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var sourceSpan = diagnostic.Location.SourceSpan; - var invocation = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - var handlerName = semanticModel.FindAvailableIdentifierName(sourceSpan.Start, "handler"); - var variable = - SyntaxFactory.LocalDeclarationStatement( - SyntaxFactory.VariableDeclaration( - SyntaxFactory.ParseTypeName("var"), - SyntaxFactory.SeparatedList( - new[] - { - SyntaxFactory.VariableDeclarator( - SyntaxFactory.Identifier(handlerName), - null, - SyntaxFactory.EqualsValueClause(invocation.Expression.WithoutLeadingTrivia().WithoutTrailingTrivia())) - }))) - .WithLeadingTrivia(invocation.Parent.GetLeadingTrivia()); - var statement = invocation.Expression.FirstAncestorOrSelfThatIsAStatement(); - var newStatement = statement.ReplaceNode(invocation.Expression, SyntaxFactory.IdentifierName(handlerName)); - var newInvocation = - SyntaxFactory.IfStatement( - SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, - SyntaxFactory.IdentifierName(handlerName), - SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)), - newStatement) - .WithTrailingTrivia(invocation.Parent.GetTrailingTrivia()); - var oldNode = statement; - var newNode = newStatement.WithAdditionalAnnotations(new SyntaxAnnotation(SyntaxAnnotatinKind)); - if (oldNode.Parent.IsEmbeddedStatementOwner()) - newNode = SyntaxFactory.Block((StatementSyntax)newNode); - var newRoot = root.ReplaceNode(oldNode, newNode); - newRoot = newRoot.InsertNodesAfter(GetMark(newRoot), new SyntaxNode[] { variable, newInvocation }); - newRoot = newRoot.RemoveNode(GetMark(newRoot), SyntaxRemoveOptions.KeepNoTrivia); - return document.WithSyntaxRoot(newRoot.WithAdditionalAnnotations(Formatter.Annotation)); - } - - private static SyntaxNode GetMark(SyntaxNode node) => - node.DescendantNodes().First(n => n.GetAnnotations(SyntaxAnnotatinKind).Any()); - } -} \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs index ceba7ca00..33163652d 100644 --- a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs @@ -11,11 +11,12 @@ namespace CodeCracker.CSharp.Design [DiagnosticAnalyzer(LanguageNames.CSharp)] public class UseInvokeMethodToFireEventAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Use Invoke Method To call on delegate"; - internal const string MessageFormat = "Use ?.Invoke operator and method to call on '{0}' delegate."; + internal const string Title = "Check for null before calling a delegate"; + internal const string MessageFormat = "Verify if delegate '{0}' is null before invoking it."; internal const string Category = SupportedCategories.Design; const string Description = "In C#6 a delegate can be invoked using the null-propagating operator (?.) and it's" - + " invoke method to avoid throwing a NullReference exception when there is no method attached to the delegate."; + + " invoke method to avoid throwing a NullReference exception when there is no method attached to the delegate. " + + "Or you can check for null before calling the delegate."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), @@ -30,7 +31,7 @@ public class UseInvokeMethodToFireEventAnalyzer : DiagnosticAnalyzer public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) => - context.RegisterSyntaxNodeAction(LanguageVersion.CSharp6, Analyzer, SyntaxKind.InvocationExpression); + context.RegisterSyntaxNodeAction(Analyzer, SyntaxKind.InvocationExpression); private static void Analyzer(SyntaxNodeAnalysisContext context) { @@ -48,11 +49,15 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) var invokedMethodSymbol = (typeInfo.ConvertedType as INamedTypeSymbol)?.DelegateInvokeMethod; if (invokedMethodSymbol == null) return; - if (!invokedMethodSymbol.ReturnsVoid && !invokedMethodSymbol.ReturnType.IsReferenceType) return; + //var cantFixWithElvis = false; + //if (!invokedMethodSymbol.ReturnsVoid && !invokedMethodSymbol.ReturnType.IsReferenceType) + // cantFixWithElvis = true; if (HasCheckForNullThatReturns(invocation, context.SemanticModel, symbol)) return; if (IsInsideANullCheck(invocation, context.SemanticModel, symbol)) return; if (symbol.IsReadOnlyAndInitializedForCertain(context)) return; + + //var properties = new Dictionary { { nameof(cantFixWithElvis), cantFixWithElvis.ToString() } }.ToImmutableDictionary(); context.ReportDiagnostic(Diagnostic.Create(Rule, invocation.GetLocation(), identifier.Identifier.Text)); } diff --git a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventCodeFixProvider.cs index a4a62017c..b3fbbfbee 100644 --- a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventCodeFixProvider.cs @@ -4,6 +4,8 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Simplification; +using System; using System.Collections.Immutable; using System.Composition; using System.Linq; @@ -15,17 +17,26 @@ namespace CodeCracker.CSharp.Design [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UseInvokeMethodToFireEventCodeFixProvider)), Shared] public class UseInvokeMethodToFireEventCodeFixProvider : CodeFixProvider { + private const string SyntaxAnnotatinKind = "CC-CopyEvent"; + public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId()); public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); + var compilation = (CSharpCompilation)await context.Document.Project.GetCompilationAsync(); + if (compilation.LanguageVersion >= LanguageVersion.CSharp6) + context.RegisterCodeFix( + CodeAction.Create("Change to ?.Invoke to call a delegate", + ct => UseInvokeAsync(context.Document, diagnostic, ct), + nameof(UseInvokeMethodToFireEventCodeFixProvider) + "_Elvis"), diagnostic); context.RegisterCodeFix( - CodeAction.Create("Change to ?.Invoke to call a delegate", ct => UseInvokeAsync(context.Document, diagnostic, ct), nameof(UseInvokeMethodToFireEventCodeFixProvider)), diagnostic); - return Task.FromResult(0); + CodeAction.Create("Copy delegate reference to a variable", + ct => CreateVariableAsync(context.Document, diagnostic, ct), + nameof(UseInvokeMethodToFireEventCodeFixProvider) + "_CopyToVariable"), diagnostic); } private async static Task UseInvokeAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) @@ -42,8 +53,78 @@ private async static Task UseInvokeAsync(Document document, Diagnostic SyntaxFactory.Token(SyntaxKind.DotToken), SyntaxFactory.IdentifierName("Invoke")), invocation.ArgumentList)) + .WithAdditionalAnnotations(Formatter.Annotation) + .WithTrailingTrivia(invocation.GetTrailingTrivia()); + var identifier = (IdentifierNameSyntax)invocation.Expression; + var semanticModel = await document.GetSemanticModelAsync(cancellationToken); + var typeInfo = semanticModel.GetTypeInfo(identifier, cancellationToken); + var symbol = semanticModel.GetSymbolInfo(identifier).Symbol; + var invokedMethodSymbol = ((INamedTypeSymbol)typeInfo.ConvertedType).DelegateInvokeMethod; + ExpressionSyntax newNode = newInvocation; + if (!invokedMethodSymbol.ReturnsVoid && !invokedMethodSymbol.ReturnType.IsReferenceType && !(invocation.Parent is ExpressionStatementSyntax)) + { + var typeName = invokedMethodSymbol.ReturnType.GetFullName(false); + var defaultValue = SyntaxFactory.DefaultExpression(SyntaxFactory.ParseName(typeName) + .WithAdditionalAnnotations(Simplifier.Annotation)); + newNode = SyntaxFactory.BinaryExpression(SyntaxKind.CoalesceExpression, newInvocation, defaultValue) .WithAdditionalAnnotations(Formatter.Annotation); - return document.WithSyntaxRoot(root.ReplaceNode(invocation, newInvocation).WithTrailingTrivia(invocation.GetTrailingTrivia())); + if (invocation.Parent is BinaryExpressionSyntax) + { + var binary = (BinaryExpressionSyntax)invocation.Parent; + if (binary.Right.Equals(invocation.Parent) + && (binary.IsKind(SyntaxKind.BitwiseAndExpression) + || binary.IsKind(SyntaxKind.ExclusiveOrExpression) + || binary.IsKind(SyntaxKind.BitwiseOrExpression) + || binary.IsKind(SyntaxKind.LogicalAndExpression)) + || binary.IsKind(SyntaxKind.LogicalOrExpression) + || binary.IsKind(SyntaxKind.CoalesceExpression)) + newNode = SyntaxFactory.ParenthesizedExpression(newNode); + } + } + var newRoot = root.ReplaceNode(invocation, newNode); + return document.WithSyntaxRoot(newRoot); } + + private async static Task CreateVariableAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var sourceSpan = diagnostic.Location.SourceSpan; + var invocation = root.FindToken(sourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); + var semanticModel = await document.GetSemanticModelAsync(cancellationToken); + var handlerName = semanticModel.FindAvailableIdentifierName(sourceSpan.Start, "handler"); + var variable = + SyntaxFactory.LocalDeclarationStatement( + SyntaxFactory.VariableDeclaration( + SyntaxFactory.ParseTypeName("var"), + SyntaxFactory.SeparatedList( + new[] + { + SyntaxFactory.VariableDeclarator( + SyntaxFactory.Identifier(handlerName), + null, + SyntaxFactory.EqualsValueClause(invocation.Expression.WithoutLeadingTrivia().WithoutTrailingTrivia())) + }))) + .WithLeadingTrivia(invocation.Parent.GetLeadingTrivia()); + var statement = invocation.Expression.FirstAncestorOrSelfThatIsAStatement(); + var newStatement = statement.ReplaceNode(invocation.Expression, SyntaxFactory.IdentifierName(handlerName)); + var newInvocation = + SyntaxFactory.IfStatement( + SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, + SyntaxFactory.IdentifierName(handlerName), + SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)), + newStatement) + .WithTrailingTrivia(invocation.Parent.GetTrailingTrivia()); + var oldNode = statement; + var newNode = newStatement.WithAdditionalAnnotations(new SyntaxAnnotation(SyntaxAnnotatinKind)); + if (oldNode.Parent.IsEmbeddedStatementOwner()) + newNode = SyntaxFactory.Block((StatementSyntax)newNode); + var newRoot = root.ReplaceNode(oldNode, newNode); + newRoot = newRoot.InsertNodesAfter(GetMark(newRoot), new SyntaxNode[] { variable, newInvocation }); + newRoot = newRoot.RemoveNode(GetMark(newRoot), SyntaxRemoveOptions.KeepNoTrivia); + return document.WithSyntaxRoot(newRoot.WithAdditionalAnnotations(Formatter.Annotation)); + } + + private static SyntaxNode GetMark(SyntaxNode node) => + node.DescendantNodes().First(n => n.GetAnnotations(SyntaxAnnotatinKind).Any()); } } \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index cad9ad940..156dc6285 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -18,7 +18,6 @@ public enum DiagnosticId TernaryOperator_Return = 13, TernaryOperator_Assignment = 14, UnnecessaryParenthesis = 15, - CopyEventToVariableBeforeFire = 16, SwitchToAutoProp = 17, ExistenceOperator = 18, ConvertToSwitch = 19, diff --git a/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs b/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs index b7bd2ee4f..cc3802231 100644 --- a/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs +++ b/src/Common/CodeCracker.Common/Extensions/AnalyzerExtensions.cs @@ -125,6 +125,8 @@ public static string GetLastIdentifierIfQualiedTypeName(this string typeName) public static string GetFullName(this ISymbol symbol, bool addGlobal = true) { + if (symbol.Kind == SymbolKind.TypeParameter) + return symbol.ToString(); var fullName = symbol.Name; var containingSymbol = symbol.ContainingSymbol; while (!(containingSymbol is INamespaceSymbol)) diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 0cac11358..8a756946c 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -162,7 +162,6 @@ - diff --git a/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs b/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs deleted file mode 100644 index e681b3057..000000000 --- a/test/CSharp/CodeCracker.Test/Design/CopyEventToVariableBeforeFireTests.cs +++ /dev/null @@ -1,827 +0,0 @@ -using CodeCracker.CSharp.Design; -using Microsoft.CodeAnalysis; -using Xunit; - -namespace CodeCracker.Test.CSharp.Design -{ - public class CopyEventToVariableBeforeFireTests : CodeFixVerifier - { - [Fact] - public async void WarningIfEventIsFiredDirectly() - { - const string test = @" - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfCustomEventIsFiredDirectly() - { - const string test = @" - public class MyArgs : System.EventArgs - { - public string Info { get; set; } - } - - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - MyEvent(this, new MyArgs() { Info = ""ping"" }); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfCustomEventWithCustomDelegateIsFiredDirectly() - { - const string test = @" - public class MyArgs : System.EventArgs - { - public string Info { get; set; } - } - - public delegate void Executed (object sender, MyArgs args); - - public class MyClass - { - public event Executed MyEvent; - - public void Execute() - { - MyEvent(this, new MyArgs() { Info = ""ping"" }); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 15, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void NotWarningIfEventIsCopiedToLocalVariableBeforeFire() - { - const string test = @" - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - var handler = MyEvent; - if (handler != null) - handler(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void WarningIfEventIsReadOnlyButNotAssignedInConstructor() - { - const string test = @" - public class MyClass - { - readonly int SomeOtherField; - readonly System.EventHandler MyEvent; - - public MyClass() - { - SomeOtherField = 42; - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedInIfInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool shouldAssign) - { - if(shouldAssign) - { - MyEvent = (sender, args) => { }; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedInForeachInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(int[] values) - { - foreach(var value in values) - { - MyEvent = (sender, args) => { }; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedInForInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(int number) - { - for(int i = 0; i < number; i++) - { - MyEvent = (sender, args) => { }; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedInWhileInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(int number) - { - while(number > 0) - { - MyEvent = (sender, args) => { }; - number--; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedAfterReturnInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool returnEarly) - { - if(returnEarly) - { - return; - } - MyEvent = (sender, args) => { }; - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedToNullRegularAssignmentOnFieldDeclaration() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent = null; - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedToNullInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool returnEarly) - { - MyEvent = null; - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedToNullAfterRegularAssignmentInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool returnEarly) - { - MyEvent = (sender, args) => { }; - MyEvent = null; - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedInAllSwitchCasesButNoDefaultInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(int value) - { - switch(value) - { - case 1: MyEvent = (sender, args) => { }; break; - case 2: MyEvent = (sender, args) => { }; break; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndAssignedInASwitchCaseButNotAllInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(int value) - { - switch(value) - { - case 1: MyEvent = (sender, args) => { }; break; - default: break; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - var expected = new DiagnosticResult - { - Id = DiagnosticId.CopyEventToVariableBeforeFire.ToDiagnosticId(), - Message = "Copy the 'MyEvent' event to a variable before firing it.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - } - - [Fact] - public async void NotWarningIfEventIsReadOnlyAndAssignedInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass() - { - MyEvent = (sender, args) => { }; - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfEventIsReadOnlyAndAssignedInBlockInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool shouldAssign) - { - { - MyEvent = (sender, args) => { }; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfEventIsReadOnlyAndAssignedInIfAndElseInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool shouldAssign) - { - if(shouldAssign) - { - MyEvent = (sender, args) => { }; - } - else - { - MyEvent = (sender, args) => { }; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfEventIsReadOnlyAndAssignedInAllSwitchCasesInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(int value) - { - switch(value) - { - case 1: MyEvent = (sender, args) => { }; break; - case 2: MyEvent = (sender, args) => { }; break; - default: MyEvent = (sender, args) => { }; break; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void WarningIfEventIsReadOnlyAndReturnAfterAssignmentInConstructor() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent; - - public MyClass(bool returnEarly) - { - MyEvent = (sender, args) => { }; - if(returnEarly) - { - return; - } - } - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfEventIsReadOnlyAndAssignedOnFieldDeclaration() - { - const string test = @" - public class MyClass - { - readonly System.EventHandler MyEvent = (sender, args) => { }; - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfIsNotAnEvent() - { - const string test = @" - public class MyClass - { - public void Execute() - { - MyClass.Run(null); - } - - public static void Run(object obj) - { - - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfIsAParameter() - { - const string test = @" - public class MyClass - { - public void Execute(Action action) - { - action(); - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void WhenEventIsFiredDirectlyShouldCopyItToVariable() - { - const string source = @" - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - MyEvent(this, System.EventArgs.Empty); - } - }"; - - const string fixtest = @" - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - var handler = MyEvent; - if (handler != null) - handler(this, System.EventArgs.Empty); - } - }"; - - await VerifyCSharpFixAsync(source, fixtest, 0); - } - - [Fact] - public async void KeepCommentsWhenReplacedWithCodeFix() - { - const string source = @" - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - //comment - MyEvent(this, System.EventArgs.Empty); //Some Comment - } - }"; - - const string fixtest = @" - public class MyClass - { - public event System.EventHandler MyEvent; - - public void Execute() - { - //comment - var handler = MyEvent; - if (handler != null) - handler(this, System.EventArgs.Empty); //Some Comment - } - }"; - - await VerifyCSharpFixAsync(source, fixtest, 0); - } - - [Fact] - public async void FixWhenInvocationIsInsideABlockWithoutBraces() - { - const string source = @" - public class MyClass - { - public event System.EventHandler MyEvent; - bool raiseEvents = true; - - public void Execute() - { - if (raiseEvents) MyEvent(this, System.EventArgs.Empty); - } - }"; - - const string fixtest = @" - public class MyClass - { - public event System.EventHandler MyEvent; - bool raiseEvents = true; - - public void Execute() - { - if (raiseEvents) - { - var handler = MyEvent; - if (handler != null) - handler(this, System.EventArgs.Empty); - } - } - }"; - - await VerifyCSharpFixAsync(source, fixtest, 0); - } - - [Fact] - public async void IgnoreMemberAccess() - { - var test = @"var tuple = new Tuple(1, null); -tuple.Item2();".WrapInCSharpMethod(); - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void NotWarningIfExpressionBodied() - { - const string test = @" - public class MyClass - { - public int Foo(int par1, int par2) => FuncCalc(par1,par2); - - public int FuncCalc(int p1, int p2) - { - return p1*p2; - } - - }"; - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - - [Fact] - public async void FixWhenInsideExpression() - { - var code = @" -public System.Func AllowInteraction { get; protected set; } -protected bool AllowedInteraction() -{ - if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) - { - return false; - } - return true; -}".WrapInCSharpClass(); - var fix = @" -public System.Func AllowInteraction { get; protected set; } -protected bool AllowedInteraction() -{ - var handler = AllowInteraction; - if (handler != null) - if (!handler("""") || 1 == System.DateTime.Now.Second) - { - return false; - } - return true; -}".WrapInCSharpClass(); - await VerifyCSharpFixAsync(code, fix); - } - - [Fact] - public async void FixWhenInsideExpressionAndNameAlreadyExists() - { - var code = @" -public System.Func AllowInteraction { get; protected set; } -protected bool AllowedInteraction() -{ - var handler = 1; - if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) - { - return false; - } - return true; -}".WrapInCSharpClass(); - var fix = @" -public System.Func AllowInteraction { get; protected set; } -protected bool AllowedInteraction() -{ - var handler = 1; - var handler1 = AllowInteraction; - if (handler1 != null) - if (!handler1("""") || 1 == System.DateTime.Now.Second) - { - return false; - } - return true; -}".WrapInCSharpClass(); - await VerifyCSharpFixAsync(code, fix); - } - } -} \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs index db9e72c7a..810d8a426 100644 --- a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs @@ -56,6 +56,350 @@ public void Execute() await VerifyCSharpDiagnosticAsync(test, expected); } + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedInIfInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(bool shouldAssign) + { + if(shouldAssign) + { + MyEvent = (sender, args) => { }; + } + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedInForeachInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(int[] values) + { + foreach(var value in values) + { + MyEvent = (sender, args) => { }; + } + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedInForInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(int number) + { + for(int i = 0; i < number; i++) + { + MyEvent = (sender, args) => { }; + } + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedInWhileInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(int number) + { + while(number > 0) + { + MyEvent = (sender, args) => { }; + number--; + } + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedAfterReturnInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(bool returnEarly) + { + if(returnEarly) + { + return; + } + MyEvent = (sender, args) => { }; + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedToNullRegularAssignmentOnFieldDeclaration() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent = null; + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedToNullInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(bool returnEarly) + { + MyEvent = null; + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedToNullAfterRegularAssignmentInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(bool returnEarly) + { + MyEvent = (sender, args) => { }; + MyEvent = null; + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedInAllSwitchCasesButNoDefaultInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(int value) + { + switch(value) + { + case 1: MyEvent = (sender, args) => { }; break; + case 2: MyEvent = (sender, args) => { }; break; + } + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void WarningIfEventIsReadOnlyAndAssignedInASwitchCaseButNotAllInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass(int value) + { + switch(value) + { + case 1: MyEvent = (sender, args) => { }; break; + default: break; + } + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), + Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async void NotWarningIfEventIsReadOnlyAndAssignedInConstructor() + { + const string test = @" + public class MyClass + { + readonly System.EventHandler MyEvent; + + public MyClass() + { + MyEvent = (sender, args) => { }; + } + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] public async void AcceptExpressionBodiedMethods() { @@ -466,13 +810,289 @@ public static TReturn Method(System.Func getter) where T } [Fact] - public async void WhenMethodInvokedWithNonReferenceTypeHasNoDiagnostic() + public async void WhenMethodInvokedWithNonReferenceTypeHasOnlyIfNullDiagnostic() { var test = @" + public static TReturn Method(System.Func getter) where TReturn : struct + { + return getter?.Invoke(default(T)) ?? default(TReturn); + }".WrapInCSharpClass(); + await VerifyCSharpHasNumberOfCodeActions(test, 1); + } + + public static TReturn Method(System.Func getter) where TReturn : struct + { + getter?.Invoke(default(T)); + return getter?.Invoke(default(T)) ?? default(TReturn); + } + + [Fact] + public async void FixWithInvokeWithNonReferenceType() + { + var source = @" + public static TReturn Method(System.Func getter) where T : System.Attribute where TReturn : struct + { + return getter(default(T)); + }".WrapInCSharpClass(); + var fix = @" + public static TReturn Method(System.Func getter) where T : System.Attribute where TReturn : struct + { + return getter?.Invoke(default(T)) ?? default(TReturn); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fix, codeFixIndex: 0); + } + + [Fact] + public async void FixWithCheckForNullWithNonReferenceType() + { + var source = @" public static TReturn Method(System.Func getter) where T : System.Attribute where TReturn : struct { return getter(default(T)); }".WrapInCSharpClass(); + var fix = @" + public static TReturn Method(System.Func getter) where T : System.Attribute where TReturn : struct + { + var handler = getter; + if (handler != null) + return handler(default(T)); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fix, codeFixIndex: 1, allowNewCompilerDiagnostics: true); + } + + [Fact] + public async void FixWithCheckForNullAndKeepCommentsWhenReplacedWithCodeFix() + { + const string source = @" + public class MyClass + { + public event System.EventHandler MyEvent; + + public void Execute() + { + //comment + MyEvent(this, System.EventArgs.Empty); //Some Comment + } + }"; + + const string fixtest = @" + public class MyClass + { + public event System.EventHandler MyEvent; + + public void Execute() + { + //comment + var handler = MyEvent; + if (handler != null) + handler(this, System.EventArgs.Empty); //Some Comment + } + }"; + await VerifyCSharpFixAsync(source, fixtest, 1); + } + + [Fact] + public async void FixWhenInvocationIsInsideABlockWithoutBraces() + { + const string source = @" + public class MyClass + { + public event System.EventHandler MyEvent; + bool raiseEvents = true; + + public void Execute() + { + if (raiseEvents) MyEvent(this, System.EventArgs.Empty); + } + }"; + + const string fixtest = @" + public class MyClass + { + public event System.EventHandler MyEvent; + bool raiseEvents = true; + + public void Execute() + { + if (raiseEvents) + { + var handler = MyEvent; + if (handler != null) + handler(this, System.EventArgs.Empty); + } + } + }"; + + await VerifyCSharpFixAsync(source, fixtest, 1); + } + + [Fact] + public async void OnlyOneFixIfExpressionBodied() + { + const string test = @" + public class MyClass + { + public int Foo(int par1, int par2) => FuncCalc(par1,par2); + + public int FuncCalc(int p1, int p2) + { + return p1*p2; + } + }"; + await VerifyCSharpHasNumberOfCodeActions(test, 1); + } + + [Fact] + public async void FixWhenInsideExpressionWithInvoke() + { + var code = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + var fix = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + if (!AllowInteraction?.Invoke("""") ?? default(bool) || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(code, fix); + } + + [Fact] + public async void FixWhenInsideABinaryExpressionWithPrecedenceWithInvoke() + { + var code = @" +void Foo(Func f) +{ + var b = true; + if (b || f()) + { + } +}".WrapInCSharpClass(); + var fix = @" +void Foo(Func f) +{ + var b = true; + if (b || (f?.Invoke() ?? default(bool))) + { + } +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(code, fix); + } + + [Fact] + public async void FixWhenInsideExpressionWithCheckForNull() + { + var code = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + var fix = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + var handler = AllowInteraction; + if (handler != null) + if (!handler("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(code, fix, 1); + } + + [Fact] + public async void FixWhenInsideExpressionAndNameAlreadyExists() + { + var code = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + var handler = 1; + if (!AllowInteraction("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + var fix = @" +public System.Func AllowInteraction { get; protected set; } +protected bool AllowedInteraction() +{ + var handler = 1; + var handler1 = AllowInteraction; + if (handler1 != null) + if (!handler1("""") || 1 == System.DateTime.Now.Second) + { + return false; + } + return true; +}".WrapInCSharpClass(); + await VerifyCSharpFixAsync(code, fix, 1); + } + + [Fact] + public async void WhenEventIsFiredDirectlyShouldCopyItToVariable() + { + const string source = @" + public class MyClass + { + public event System.EventHandler MyEvent; + + public void Execute() + { + MyEvent(this, System.EventArgs.Empty); + } + }"; + + const string fixtest = @" + public class MyClass + { + public event System.EventHandler MyEvent; + + public void Execute() + { + var handler = MyEvent; + if (handler != null) + handler(this, System.EventArgs.Empty); + } + }"; + + await VerifyCSharpFixAsync(source, fixtest, 1); + } + + [Fact] + public async void NotWarningIfEventIsCopiedToLocalVariableBeforeFire() + { + const string test = @" + public class MyClass + { + public event System.EventHandler MyEvent; + + public void Execute() + { + var handler = MyEvent; + if (handler != null) + handler(this, System.EventArgs.Empty); + } + }"; await VerifyCSharpHasNoDiagnosticsAsync(test); } diff --git a/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs b/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs index 92a423897..b6cc7416f 100644 --- a/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs +++ b/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs @@ -323,6 +323,45 @@ private async static Task VerifyFixAllAsync(string language, DiagnosticAnalyzer } } + /// + /// Called to verify how many code actions a code fix registered + /// Creates a Document from the source string, then gets diagnostics on it and verify if it has x number of code actions registred. + /// It will fail the test if it has a different number of code actions registred to it. + /// + /// A class in the form of a string before the CodeFix was applied to it + /// The codefix to be applied to the code wherever the relevant Diagnostic is found + /// C# language version used for compiling the test project, required unless you inform the VB language version. + /// The expected number of code actions provided by the code fix. + protected async Task VerifyCSharpHasNumberOfCodeActions(string source, int numberOfCodeActions, CodeFixProvider codeFixProvider = null, LanguageVersion languageVersionCSharp = LanguageVersion.CSharp6) => + await VerifyNumberOfCodeActions(LanguageNames.CSharp, GetDiagnosticAnalyzer(), codeFixProvider ?? GetCodeFixProvider(), source, numberOfCodeActions, languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic14).ConfigureAwait(true); + + /// + /// General verifier for a diagnostics that verifies how many code actions a code fix registered. + /// Creates a Document from the source string, then gets diagnostics on it and verify if it has x number of code actions registred. + /// It will fail the test if it has a different number of code actions registred to it. + /// + /// The language the source code is in + /// The analyzer to be applied to the source code + /// The codefix to be applied to the code wherever the relevant Diagnostic is found + /// A class in the form of a string before the CodeFix was applied to it + /// C# language version used for compiling the test project, required unless you inform the VB language version. + /// VB language version used for compiling the test project, required unless you inform the C# language version. + /// The expected number of code actions provided by the code fix. + private async static Task VerifyNumberOfCodeActions(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string source, int numberOfCodeActions, LanguageVersion languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion languageVersionVB) + { + var document = CreateDocument(source, language, languageVersionCSharp, languageVersionVB); + var analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzer, new[] { document }).ConfigureAwait(true); + + foreach (var analyzerDiagnostic in analyzerDiagnostics) + { + var actions = new List(); + var context = new CodeFixContext(document, analyzerDiagnostic, (a, d) => actions.Add(a), CancellationToken.None); + await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(true); + var numberOfCodeActionsFound = actions.Count(); + Assert.True(numberOfCodeActions == numberOfCodeActionsFound, $"Should have {numberOfCodeActions} code actions registered for diagnostic '{analyzerDiagnostic.Id}' but got {numberOfCodeActionsFound}."); + } + } + /// /// Called to test a C# codefix when it should not had been registered /// From 24f65a83cdb53d7664a682e789945ffa9b596cb0 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 01:41:22 -0300 Subject: [PATCH 036/234] Change from Debug build config to Release --- CodeCracker.CSharp.sln | 12 +++++++++++- appveyor.yml | 2 +- build.targets.ps1 | 18 +++++++++--------- src/CSharp/CodeCracker/CodeCracker.nuspec | 6 +++--- src/CodeCracker.nuspec | 4 ++-- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 6 +++--- test/CSharp/AnalyzeCecil.ps1 | 6 +++--- test/CSharp/AnalyzeCoreFx.ps1 | 4 ++-- test/CSharp/AnalyzeRoslyn.ps1 | 6 +++--- 9 files changed, 37 insertions(+), 27 deletions(-) diff --git a/CodeCracker.CSharp.sln b/CodeCracker.CSharp.sln index 55aa52a2b..2f52cf033 100644 --- a/CodeCracker.CSharp.sln +++ b/CodeCracker.CSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F5240AD-2B4E-48A4-B9FC-7D19DACEF2CD}" ProjectSection(SolutionItems) = preProject @@ -49,6 +49,7 @@ Global Debug|Any CPU = Debug|Any CPU DebugNoVsix|Any CPU = DebugNoVsix|Any CPU Release|Any CPU = Release|Any CPU + ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -57,29 +58,38 @@ Global {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.ActiveCfg = Release|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.Build.0 = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.Build.0 = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.ActiveCfg = Release|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.Build.0 = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/appveyor.yml b/appveyor.yml index 0eae120fe..c89ed6dff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: 1.0.0.{build} skip_tags: true -configuration: DebugNoVsix +configuration: ReleaseNoVsix init: - git config --global core.autocrlf true diff --git a/build.targets.ps1 b/build.targets.ps1 index 2e7030fc0..59ddf710b 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -19,13 +19,13 @@ Properties { $openCoverExe = "$packagesDir\OpenCover.4.6.166\tools\OpenCover.Console.exe" $testDllCS = "CodeCracker.Test.CSharp.dll" $testDllVB = "CodeCracker.Test.VisualBasic.dll" - $testDirCS = "$testDir\CSharp\CodeCracker.Test\bin\Debug" - $testDirVB = "$testDir\VisualBasic\CodeCracker.Test\bin\Debug" + $testDirCS = "$testDir\CSharp\CodeCracker.Test\bin\Release" + $testDirVB = "$testDir\VisualBasic\CodeCracker.Test\bin\Release" $logDir = "$rootDir\log" $outputXml = "$logDir\CodeCoverageResults.xml" $reportGeneratorExe = "$packagesDir\ReportGenerator.2.3.5.0\tools\ReportGenerator.exe" $coverageReportDir = "$logDir\codecoverage\" - $converallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" + $coverallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" $isRelease = $isAppVeyor -and ($env:APPVEYOR_REPO_BRANCH -eq "release") $isPullRequest = $env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null } @@ -51,16 +51,16 @@ Task Build-VB -depends Prepare-Build, Build-Only-VB Task Build-Only -depends Build-Only-CS, Build-Only-VB Task Build-Only-CS { if ($isAppVeyor) { - Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=DebugNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } + Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } } else { - Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=DebugNoVsix } + Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } } } Task Build-Only-VB { if ($isAppVeyor) { - Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=DebugNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } + Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } } else { - Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=DebugNoVsix } + Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } } } @@ -128,7 +128,7 @@ function PackNuget($language, $dir, $nuspecFile, $nupkgFile) { [xml]$xml = cat $nuspecFile $nupkgFile = $nupkgFile -f $xml.package.metadata.version Write-Host "Nupkg path is $nupkgFile" - . $nugetExe pack $nuspecFile -Properties "Configuration=Debug;Platform=AnyCPU" -OutputDirectory $dir + . $nugetExe pack $nuspecFile -OutputDirectory $dir ls $nupkgFile Write-Host "Nuget packed for $language!" Write-Host "Pushing nuget artifact for $language..." @@ -220,6 +220,6 @@ function RunTestWithCoverage($fullTestDllPaths) { Exec { . $reportGeneratorExe -verbosity:Info -reports:$outputXml -targetdir:$coverageReportDir } if ($env:COVERALLS_REPO_TOKEN -ne $null) { Write-Host -ForegroundColor DarkBlue "Uploading coverage report to Coveralls.io" - Exec { . $converallsNetExe --opencover $outputXml --full-sources } + Exec { . $coverallsNetExe --opencover $outputXml --full-sources } } } \ No newline at end of file diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index fb1a57fee..974df8851 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -13,15 +13,15 @@ A analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. - Third alpha release - Copyright CodeCracker 2014-2015 + See https://github.com/code-cracker/code-cracker/blob/master/CHANGELOG.md + Copyright CodeCracker 2014-2016 roslyn, analyzers - + diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index e34681210..9ea132644 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -15,8 +15,8 @@ You probably don't want this package directly, search for the C# or Visual Basic specific packages (codecracker.CSharp and codecracker.VisualBasic). This will install both. This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. - First alpha release - Copyright CodeCracker 2014 + See https://github.com/code-cracker/code-cracker/blob/master/CHANGELOG.md + Copyright CodeCracker 2014-2016 roslyn, analyzers diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index 4245b4eeb..d5a8ec65e 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -13,15 +13,15 @@ A analyzer library for Visual Basic that uses Roslyn to produce refactorings, code analysis, and other niceties. This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. - Third alpha release - Copyright CodeCracker 2014-2015 + See https://github.com/code-cracker/code-cracker/blob/master/CHANGELOG.md + Copyright CodeCracker 2014-2016 roslyn, analyzers - + diff --git a/test/CSharp/AnalyzeCecil.ps1 b/test/CSharp/AnalyzeCecil.ps1 index 6f9902b76..a2700956e 100644 --- a/test/CSharp/AnalyzeCecil.ps1 +++ b/test/CSharp/AnalyzeCecil.ps1 @@ -3,8 +3,8 @@ $baseDir = "$([System.IO.Path]::GetTempPath())$([System.Guid]::NewGuid().ToStri $projectDir = "$baseDir\cecil" $logDir = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\log") $logFile = "$logDir\cecil.log" -$analyzerDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Debug\CodeCracker.CSharp.dll") -$analyzerCommonDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Debug\CodeCracker.Common.dll") +$analyzerDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Release\CodeCracker.CSharp.dll") +$analyzerCommonDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Release\CodeCracker.Common.dll") $gitPath = "https://github.com/jbevain/cecil.git" if (Test-Path "C:\p\cecil") { $gitPath = "c:\p\cecil" @@ -78,7 +78,7 @@ if ($ccBuildErrors -ne $null) write-host "Errors found (see $logFile):" foreach($ccBuildError in $ccBuildErrors) { - Write-Host -ForegroundColor DarkRed "$($ccBuildError.LineNumber) $($ccBuildError.Line)" + Write-Host -ForegroundColor DarkRed "$($ccBuildError.LineNumber) $($ccBuildError.Line)" } throw "Errors found on the cecil analysis" } \ No newline at end of file diff --git a/test/CSharp/AnalyzeCoreFx.ps1 b/test/CSharp/AnalyzeCoreFx.ps1 index e6f28ab9c..c418b147a 100644 --- a/test/CSharp/AnalyzeCoreFx.ps1 +++ b/test/CSharp/AnalyzeCoreFx.ps1 @@ -3,7 +3,7 @@ $baseDir = "$([System.IO.Path]::GetTempPath())$([System.Guid]::NewGuid().ToStri $projectDir = "$baseDir\corefx" $logDir = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\log") $logFile = "$logDir\corefx.log" -$analyzerDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Debug\CodeCracker.CSharp.dll") +$analyzerDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Release\CodeCracker.CSharp.dll") $gitPath = "https://github.com/dotnet/corefx.git" if (Test-Path "C:\proj\corefx") { $gitPath = "C:\proj\corefx" @@ -69,7 +69,7 @@ if ($ccBuildErrors -ne $null) Write-Host "Errors found (see $logFile):" foreach($ccBuildError in $ccBuildErrors) { - Write-Host -ForegroundColor DarkRed "$($ccBuildError.LineNumber) $($ccBuildError.Line)" + Write-Host -ForegroundColor DarkRed "$($ccBuildError.LineNumber) $($ccBuildError.Line)" } throw "Errors found on the corefx analysis" } diff --git a/test/CSharp/AnalyzeRoslyn.ps1 b/test/CSharp/AnalyzeRoslyn.ps1 index efd208be6..0ac60d2fb 100644 --- a/test/CSharp/AnalyzeRoslyn.ps1 +++ b/test/CSharp/AnalyzeRoslyn.ps1 @@ -3,8 +3,8 @@ $baseDir = "$([System.IO.Path]::GetTempPath())$([System.Guid]::NewGuid().ToStri $projectDir = "$baseDir\roslyn" $logDir = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\log") $logFile = "$logDir\roslyn.log" -$analyzerDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Debug\CodeCracker.CSharp.dll") -$analyzerDllVB = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\VisualBasic\CodeCracker\bin\Debug\CodeCracker.VisualBasic.dll") +$analyzerDll = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\CSharp\CodeCracker\bin\Release\CodeCracker.CSharp.dll") +$analyzerDllVB = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\src\VisualBasic\CodeCracker\bin\Release\CodeCracker.VisualBasic.dll") $gitPath = "https://github.com/dotnet/roslyn.git" if (Test-Path "c:\proj\roslyn") { $gitPath = "c:\proj\roslyn" @@ -101,7 +101,7 @@ if ($ccBuildErrors -ne $null) Write-Host "Errors found (see $logFile):" foreach($ccBuildError in $ccBuildErrors) { - Write-Host -ForegroundColor DarkRed "$($ccBuildError.LineNumber) $($ccBuildError.Line)" + Write-Host -ForegroundColor DarkRed "$($ccBuildError.LineNumber) $($ccBuildError.Line)" } throw "Errors found on the roslyn analysis" } \ No newline at end of file From cd121d14f66f5d1836386bfa8272e35ddb8beb29 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 01:48:40 -0300 Subject: [PATCH 037/234] Create ReleaseNoVsix build config for global and vb slns --- CodeCracker.VisualBasic.sln | 12 +++++++++++- CodeCracker.sln | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CodeCracker.VisualBasic.sln b/CodeCracker.VisualBasic.sln index 049aa9a2c..6b903192a 100644 --- a/CodeCracker.VisualBasic.sln +++ b/CodeCracker.VisualBasic.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" EndProject @@ -45,6 +45,7 @@ Global Debug|Any CPU = Debug|Any CPU DebugNoVsix|Any CPU = DebugNoVsix|Any CPU Release|Any CPU = Release|Any CPU + ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -53,29 +54,38 @@ Global {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.Build.0 = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CodeCracker.sln b/CodeCracker.sln index 0b2e60b2a..8061066fb 100644 --- a/CodeCracker.sln +++ b/CodeCracker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" EndProject @@ -61,6 +61,7 @@ Global Debug|Any CPU = Debug|Any CPU DebugNoVsix|Any CPU = DebugNoVsix|Any CPU Release|Any CPU = Release|Any CPU + ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -69,46 +70,60 @@ Global {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.Build.0 = Debug|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.ActiveCfg = Release|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.Build.0 = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.Build.0 = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.ActiveCfg = Release|Any CPU {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.Build.0 = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.Build.0 = Debug|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.Build.0 = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 6a7bd84f00c77a67a1e66693375cb0a9e4f2a594 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 02:28:42 -0300 Subject: [PATCH 038/234] Bump version to 1.0.0 :shipit: --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CSharp/CodeCracker/Properties/AssemblyInfo.cs | 2 +- src/CodeCracker.nuspec | 6 +++--- src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs | 4 ++-- .../CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 2 +- src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb | 4 ++-- test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Test.Common/Properties/AssemblyInfo.cs | 2 +- .../VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index 8c461be91..ceaef7c59 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for C# An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index 974df8851..bd9ae7cc4 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.CSharp - 1.0.0-rc6 + 1.0.0 CodeCracker for C# giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs index 9bbcf16e1..0b5e5b22a 100644 --- a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.13")] +[assembly: AssemblyFileVersion("1.0.0.14")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index 9ea132644..67e27ad9d 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker - 1.0.0-rc6 + 1.0.0 CodeCracker for C# and VB giggio,elemarjr,carloscds giggio,elemarjr,carloscds @@ -19,8 +19,8 @@ This is a community project, free and open source. Everyone is invited to contri Copyright CodeCracker 2014-2016 roslyn, analyzers - - + + diff --git a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs index ae8fadbe6..266a6438b 100644 --- a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs +++ b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs @@ -14,6 +14,6 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.13")] +[assembly: AssemblyFileVersion("1.0.0.14")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] -[assembly: InternalsVisibleTo("CodeCracker.Test.VisualBasic")] +[assembly: InternalsVisibleTo("CodeCracker.Test.VisualBasic")] \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index baa76ca16..3cfea306c 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for Visual Basic An analyzer library for VB that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index d5a8ec65e..3be6daa7e 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.VisualBasic - 1.0.0-rc6 + 1.0.0 CodeCracker for Visual Basic giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb index 533dd3d92..e1f2b3667 100644 --- a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb +++ b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb @@ -14,5 +14,5 @@ Imports System.Runtime.InteropServices - - + + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs index 0440a3f4b..71eb11924 100644 --- a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs +++ b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.13")] +[assembly: AssemblyFileVersion("1.0.0.14")] \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs index 9b9d5375b..587387784 100644 --- a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en-us")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.13")] +[assembly: AssemblyFileVersion("1.0.0.14")] \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb index cb4bb031a..b5de9452d 100644 --- a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb +++ b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb @@ -14,4 +14,4 @@ Imports System.Runtime.InteropServices - + \ No newline at end of file From 70d3379e475a69b8f4790669063840f2cda4db78 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 02:29:59 -0300 Subject: [PATCH 039/234] Skip generation/publishing of joint nuget package --- build.targets.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.targets.ps1 b/build.targets.ps1 index 59ddf710b..79813258b 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -112,7 +112,8 @@ Task Update-Nuspec-VB -precondition { return $isAppVeyor -and ($isRelease -ne $t Task Pack-Nuget -precondition { return $isAppVeyor } -depends Pack-Nuget-Joint Task Pack-Nuget-Joint -precondition { return $isAppVeyor } -depends Pack-Nuget-Csharp, Pack-Nuget-VB { - PackNuget "Joint package" "$rootDir" $nuspecPathJoint $nupkgPathJoint + #we won't be publishing the common package anymore + #PackNuget "Joint package" "$rootDir" $nuspecPathJoint $nupkgPathJoint } Task Pack-Nuget-CSharp -precondition { return $isAppVeyor } { PackNuget "C#" "$rootDir\src\CSharp" $nuspecPathCS $nupkgPathCS From 3d561402f84724cbe4530405f68345e69caa2c13 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 02:38:52 -0300 Subject: [PATCH 040/234] Use build number as `-z1234` --- build.targets.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.targets.ps1 b/build.targets.ps1 index 79813258b..933398474 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -140,7 +140,7 @@ function PackNuget($language, $dir, $nuspecFile, $nupkgFile) { function UpdateNuspec($nuspecPath, $language) { write-host "Updating version in nuspec file for $language to $buildNumber" [xml]$xml = cat $nuspecPath - $xml.package.metadata.version+="-$buildNumber" + $xml.package.metadata.version+="-z$buildNumber" write-host "Nuspec version will be $($xml.package.metadata.version)" $xml.Save($nuspecPath) write-host "Nuspec saved for $language!" From cfb5aff1108f2beb19a9ec14046d03e3dbefa5aa Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 03:27:27 -0300 Subject: [PATCH 041/234] Update changelog to 1.0.0 --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3b084bcf..7753429db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,41 @@ # Change Log +## [v1.0.0](https://github.com/code-cracker/code-cracker/tree/v1.0.0) (2016-04-03) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc6...v1.0.0) + +**Implemented enhancements:** + +- CC0016 and CC0031 are doing similar work [\#662](https://github.com/code-cracker/code-cracker/issues/662) +- Update XmlDocumentation to raise 2 different diagnostic ids [\#488](https://github.com/code-cracker/code-cracker/issues/488) + +**Fixed bugs:** + +- BUG: using null propagation foils the analysis for dispose object \(CC0022\) [\#761](https://github.com/code-cracker/code-cracker/issues/761) +- CC0011 incorrect when Where predicate uses index parameter [\#752](https://github.com/code-cracker/code-cracker/issues/752) +- BUG: Change to ternary fails with primitive numeric types \(CC0013 and CC0014\) [\#748](https://github.com/code-cracker/code-cracker/issues/748) +- CC0014 Use ternary tries to DirectCast integer to double [\#745](https://github.com/code-cracker/code-cracker/issues/745) +- BUG: CC0068 'Method is not used' should not apply to methods that have the ContractInvariantMethod attribute [\#744](https://github.com/code-cracker/code-cracker/issues/744) +- BUG: CC0057 UnusedParametersAnalyzer should not be triggered with verbatim identifier \(prefixed with @\) [\#741](https://github.com/code-cracker/code-cracker/issues/741) +- Code fix for CC0075 could break the logic of the code [\#740](https://github.com/code-cracker/code-cracker/issues/740) +- BUG: CC0016 "CopyEventToVariableBeforeFireCodeFixProvider" crashes [\#735](https://github.com/code-cracker/code-cracker/issues/735) +- CC0057 UnusedParametersAnalyzer should not be triggered by DllImport [\#733](https://github.com/code-cracker/code-cracker/issues/733) +- BUG: CC0013 \(Make Ternary\) doesn't handle comments correctly [\#725](https://github.com/code-cracker/code-cracker/issues/725) +- BUG: CC0014: You can use a ternary operator turns a+=b into a=a+b [\#724](https://github.com/code-cracker/code-cracker/issues/724) +- Bug in introduce field from constructor [\#721](https://github.com/code-cracker/code-cracker/issues/721) +- BUG: CC0090 \(xmldoc\) is raised on generated files [\#720](https://github.com/code-cracker/code-cracker/issues/720) +- BUG: CC0008 code fix removes too many lines when constructor already has initializer [\#717](https://github.com/code-cracker/code-cracker/issues/717) +- BUG: CC0067 must not fire when parameter Func\ is called in constructor. [\#712](https://github.com/code-cracker/code-cracker/issues/712) +- BUG: CC0033 \(DisposableFieldNotDisposed\) Should ignore static field [\#710](https://github.com/code-cracker/code-cracker/issues/710) +- CC0017 virtual props can create infinite loops [\#702](https://github.com/code-cracker/code-cracker/issues/702) +- CC0057: extern method parameter unused [\#701](https://github.com/code-cracker/code-cracker/issues/701) +- BUG: CC0052 \(readonly\) flags field that is used in variable initializer, which then gives compile error [\#700](https://github.com/code-cracker/code-cracker/issues/700) +- BUG: CC0017 \(create auto property\) removing modifiers \(static, virtual, etc\) [\#699](https://github.com/code-cracker/code-cracker/issues/699) +- BUG: CC0006 \(foreach\) edge case for non-writable struct field [\#698](https://github.com/code-cracker/code-cracker/issues/698) +- BUG: CC00091 Method `GetEnumerator` should never be made static [\#696](https://github.com/code-cracker/code-cracker/issues/696) +- Bug: CC0048 nested interpolations doesn't fix in one iteration [\#690](https://github.com/code-cracker/code-cracker/issues/690) +- BUG: CC0091 WPF event cannot be static [\#639](https://github.com/code-cracker/code-cracker/issues/639) +- DisposableVariableNotDisposedAnalyzer \(CC0022\) should not raise a diagnostic when returning a type that contains the disposable [\#465](https://github.com/code-cracker/code-cracker/issues/465) + ## [v1.0.0-rc6](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc6) (2016-02-01) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc5...v1.0.0-rc6) @@ -96,10 +132,13 @@ - CC0009 eats pragmas and trivia [\#493](https://github.com/code-cracker/code-cracker/issues/493) - CC0013 \(user ternary\) rule should be more careful with nullable types. \(VB\) [\#468](https://github.com/code-cracker/code-cracker/issues/468) - ## [v1.0.0-rc3](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc3) (2015-10-03) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc2...v1.0.0-rc3) +**Implemented enhancements:** + +- CC0013 Should be Information instead of Warning [\#520](https://github.com/code-cracker/code-cracker/issues/520) + **Fixed bugs:** - CC0017 Change to auto property codefix removes multiple variable declaration. [\#512](https://github.com/code-cracker/code-cracker/issues/512) @@ -120,6 +159,12 @@ ## [v1.0.0-rc2](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc2) (2015-08-19) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc1...v1.0.0-rc2) +**Implemented enhancements:** + +- Update VB Allow Members Ordering to work with Modules [\#440](https://github.com/code-cracker/code-cracker/issues/440) +- Provide an equivalence key on all code fix providers [\#417](https://github.com/code-cracker/code-cracker/issues/417) +- Unit test methods raises CC0091 - "Make \ method static" [\#404](https://github.com/code-cracker/code-cracker/issues/404) + **Fixed bugs:** - Erroneous CC0039 message [\#461](https://github.com/code-cracker/code-cracker/issues/461) @@ -138,6 +183,10 @@ ## [v1.0.0-rc1](https://github.com/code-cracker/code-cracker/tree/v1.0.0-rc1) (2015-07-23) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-beta1...v1.0.0-rc1) +**Implemented enhancements:** + +- Verify if xml docs have the correct parameters [\#357](https://github.com/code-cracker/code-cracker/issues/357) + **Fixed bugs:** - BUG: CopyEventToVariableBeforeFireCodeFixProvider throwing [\#411](https://github.com/code-cracker/code-cracker/issues/411) @@ -278,6 +327,7 @@ - Update all analyzers to use the supported categories [\#97](https://github.com/code-cracker/code-cracker/issues/97) - Detect read-only private fields and fix adding the "readonly" modifier [\#86](https://github.com/code-cracker/code-cracker/issues/86) - Offer diagnostic to allow for ordering members inside classes and structs [\#76](https://github.com/code-cracker/code-cracker/issues/76) +- Excess parameters in methods [\#44](https://github.com/code-cracker/code-cracker/issues/44) - Suggest use of stringbuilder when you have a while loop [\#34](https://github.com/code-cracker/code-cracker/issues/34) - Private set by default for automatic properties [\#32](https://github.com/code-cracker/code-cracker/issues/32) - Class that has IDisposable fields should implement IDisposable and dispose those fields [\#30](https://github.com/code-cracker/code-cracker/issues/30) @@ -352,4 +402,4 @@ -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file From 4037af5ccdb730bf5e65e22752b1127c06913646 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 3 Apr 2016 03:53:11 -0300 Subject: [PATCH 042/234] Update badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c771fb052..1a7259b4d 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ Check the official project site on [code-cracker.github.io](http://code-cracker. our task board, definition of done, definition of ready, etc. [![Build status](https://ci.appveyor.com/api/projects/status/h21sli3jkumuswyi?svg=true)](https://ci.appveyor.com/project/code-cracker/code-cracker) -[![Nuget count](https://img.shields.io/nuget/v/codecracker.svg)](https://www.nuget.org/packages/codecracker/) -[![Nuget downloads](https://img.shields.io/nuget/dt/codecracker.svg)](https://www.nuget.org/packages/codecracker/) +[![Nuget count](https://img.shields.io/nuget/v/codecracker.CSharp.svg)](https://www.nuget.org/packages/codecracker.CSharp/) +[![License](https://img.shields.io/github/license/code-cracker/code-cracker.svg)](https://github.com/code-cracker/code-cracker/blob/master/LICENSE.txt) [![Issues open](https://img.shields.io/github/issues-raw/code-cracker/code-cracker.svg)](https://huboard.com/code-cracker/code-cracker/) [![Coverage Status](https://img.shields.io/coveralls/code-cracker/code-cracker/master.svg)](https://coveralls.io/r/code-cracker/code-cracker?branch=master) [![Source Browser](https://img.shields.io/badge/Browse-Source-green.svg)](http://ccref.azurewebsites.net) From d3c536c7286b8c66eceb16b60e32def9fce15d2c Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Mon, 11 Apr 2016 22:57:22 -0300 Subject: [PATCH 043/234] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1a7259b4d..f3ae91e29 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,13 @@ changes to source control and share with your team, then you also want the Nuget To install from Nuget, for the C# version: ```powershell -Install-Package CodeCracker.CSharp -Pre +Install-Package CodeCracker.CSharp ``` Or for the Visual Basic version: ```powershell -Install-Package CodeCracker.VisualBasic -Pre +Install-Package CodeCracker.VisualBasic ``` Or use the Package Manager in Visual Studio. From 75a8304725c945d82292c913fa2863d7c408a4b1 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 15 Apr 2016 20:54:22 -0300 Subject: [PATCH 044/234] Update deps and cleanup --- build.targets.ps1 | 4 +-- src/CSharp/CodeCracker/CodeCracker.csproj | 4 +-- .../UseInvokeMethodToFireEventAnalyzer.cs | 4 --- src/CSharp/CodeCracker/packages.config | 2 +- .../CodeCracker.Common.csproj | 4 +-- src/Common/CodeCracker.Common/packages.config | 2 +- .../CodeCracker/CodeCracker.vbproj | 4 +-- src/VisualBasic/CodeCracker/packages.config | 2 +- .../CodeCracker.Test/CodeCracker.Test.csproj | 16 +++++----- .../Design/UseInvokeMethodToFireEventTests.cs | 4 +-- .../CodeCracker.Test/Style/ForInArrayTests.cs | 6 ++-- .../Style/TernaryOperatorTests.cs | 11 ------- .../Usage/JsonNetAnalyzerTests.cs | 30 ++++++++----------- .../Usage/VirtualMethodOnConstructorTests.cs | 2 +- test/CSharp/CodeCracker.Test/packages.config | 6 ++-- .../CodeCracker.Test.Common.csproj | 16 +++++----- .../Helpers/DiagnosticVerifier.Helper.cs | 1 - .../Verifiers/CodeFixVerifier.cs | 6 ++-- .../CodeCracker.Test.Common/packages.config | 10 +++---- .../CodeCracker.Test/CodeCracker.Test.vbproj | 18 +++++------ .../Style/TernaryOperatorTests.vb | 9 ------ ...sonNetTests.vb => JsonNetAnalyzerTests.vb} | 4 +-- .../CodeCracker.Test/packages.config | 6 ++-- 23 files changed, 71 insertions(+), 100 deletions(-) rename test/VisualBasic/CodeCracker.Test/Usage/{JsonNetTests.vb => JsonNetAnalyzerTests.vb} (96%) diff --git a/build.targets.ps1 b/build.targets.ps1 index 933398474..7c7e12a6a 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -16,14 +16,14 @@ Properties { $nupkgPathVB = "$rootDir\src\VisualBasic\CodeCracker.VisualBasic.{0}.nupkg" $nupkgPathJoint = "$rootDir\CodeCracker.{0}.nupkg" $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" - $openCoverExe = "$packagesDir\OpenCover.4.6.166\tools\OpenCover.Console.exe" + $openCoverExe = "$packagesDir\OpenCover.4.6.519\tools\OpenCover.Console.exe" $testDllCS = "CodeCracker.Test.CSharp.dll" $testDllVB = "CodeCracker.Test.VisualBasic.dll" $testDirCS = "$testDir\CSharp\CodeCracker.Test\bin\Release" $testDirVB = "$testDir\VisualBasic\CodeCracker.Test\bin\Release" $logDir = "$rootDir\log" $outputXml = "$logDir\CodeCoverageResults.xml" - $reportGeneratorExe = "$packagesDir\ReportGenerator.2.3.5.0\tools\ReportGenerator.exe" + $reportGeneratorExe = "$packagesDir\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe" $coverageReportDir = "$logDir\codecoverage\" $coverallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" $isRelease = $isAppVeyor -and ($env:APPVEYOR_REPO_BRANCH -eq "release") diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 0f1d5e220..e8c815a5f 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -221,8 +221,8 @@ - - + + diff --git a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs index 33163652d..c0d8ef201 100644 --- a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs @@ -49,15 +49,11 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) var invokedMethodSymbol = (typeInfo.ConvertedType as INamedTypeSymbol)?.DelegateInvokeMethod; if (invokedMethodSymbol == null) return; - //var cantFixWithElvis = false; - //if (!invokedMethodSymbol.ReturnsVoid && !invokedMethodSymbol.ReturnType.IsReferenceType) - // cantFixWithElvis = true; if (HasCheckForNullThatReturns(invocation, context.SemanticModel, symbol)) return; if (IsInsideANullCheck(invocation, context.SemanticModel, symbol)) return; if (symbol.IsReadOnlyAndInitializedForCertain(context)) return; - //var properties = new Dictionary { { nameof(cantFixWithElvis), cantFixWithElvis.ToString() } }.ToImmutableDictionary(); context.ReportDiagnostic(Diagnostic.Create(Rule, invocation.GetLocation(), identifier.Identifier.Text)); } diff --git a/src/CSharp/CodeCracker/packages.config b/src/CSharp/CodeCracker/packages.config index 776175206..442f37a31 100644 --- a/src/CSharp/CodeCracker/packages.config +++ b/src/CSharp/CodeCracker/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index 109c559bf..1ea38b03f 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -70,8 +70,8 @@ - - + + diff --git a/src/Common/CodeCracker.Common/packages.config b/src/Common/CodeCracker.Common/packages.config index c412e21be..0265a0254 100644 --- a/src/Common/CodeCracker.Common/packages.config +++ b/src/Common/CodeCracker.Common/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index 500c6b6eb..5fe35f007 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -162,8 +162,8 @@ - - + + diff --git a/src/VisualBasic/CodeCracker/packages.config b/src/VisualBasic/CodeCracker/packages.config index be0fe2547..30ff459a2 100644 --- a/src/VisualBasic/CodeCracker/packages.config +++ b/src/VisualBasic/CodeCracker/packages.config @@ -1,6 +1,6 @@  - + diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 8a756946c..f474e4208 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -40,12 +40,12 @@ false - - ..\..\..\packages\FluentAssertions.4.1.0\lib\net45\FluentAssertions.dll + + ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.dll True - - ..\..\..\packages\FluentAssertions.4.1.0\lib\net45\FluentAssertions.Core.dll + + ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.Core.dll True @@ -68,8 +68,8 @@ ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True - - ..\..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True @@ -235,8 +235,8 @@ - - + + diff --git a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs index 810d8a426..9f3239e43 100644 --- a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs @@ -817,7 +817,7 @@ public static TReturn Method(System.Func getter) where T { return getter?.Invoke(default(T)) ?? default(TReturn); }".WrapInCSharpClass(); - await VerifyCSharpHasNumberOfCodeActions(test, 1); + await VerifyCSharpHasNumberOfCodeActionsAsync(test, 1); } public static TReturn Method(System.Func getter) where TReturn : struct @@ -939,7 +939,7 @@ public int FuncCalc(int p1, int p2) return p1*p2; } }"; - await VerifyCSharpHasNumberOfCodeActions(test, 1); + await VerifyCSharpHasNumberOfCodeActionsAsync(test, 1); } [Fact] diff --git a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs index 7b333410e..780687f64 100644 --- a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs @@ -761,7 +761,7 @@ public int[] Foo [Fact] public async Task WithValueTypeNoDiagnostic() { - var source = @" + const string source = @" using System; using System.Collections.Generic; @@ -791,7 +791,7 @@ static void Goo() [Fact] public async Task WithValueTypeAndIEnumeratorDoesNotCreateDiagnostic() { - var source = @" + const string source = @" class Foo { void Bar() @@ -823,7 +823,7 @@ public System.Collections.Generic.IEnumerator GetEnumerator() [Fact] public async Task WithValueTypeListNoDiagnostic() { - var source = @" + const string source = @" using System; using System.Collections.Generic; diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 946cc60f1..68d90f96d 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -518,17 +518,6 @@ static object OnReturn() await VerifyCSharpFixAsync(source, fixtest); } - static object OnReturn() - { - var condition = true; - var aInt = 2; - var anObj = new object(); - if (condition) - return anObj; - else - return aInt; - } - [Fact] public async Task WhenUsingIfAndElseWithDirectReturnChangeToTernaryFixAll() { diff --git a/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs index aad8d95a6..d94b0be0b 100644 --- a/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs @@ -6,7 +6,7 @@ namespace CodeCracker.Test.CSharp.Usage { - public class JsonNetTests : CodeFixVerifier + public class JsonNetAnalyzerTests : CodeFixVerifier { private const string TestCode = @" using System; @@ -26,86 +26,82 @@ public Person() [Fact] public async Task IfDeserializeObjectIdentifierFoundAndJsonTextIsIncorrectCreatesDiagnostic() { - var test = string.Format(TestCode, @"Newtonsoft.Json.JsonConvert.DeserializeObject(""foo"")"); + var test = string.Format(TestCode, @"Newtonsoft.Json.JsonConvert.DeserializeObject(""foo"");"); await VerifyCSharpDiagnosticAsync(test, CreateDiagnosticResult(11, 67)); } [Fact] public async Task IfAbbreviatedDeserializeObjectIdentifierFoundAndJsonTextIsIncorrectCreatesDiagnostic() { - var test = string.Format(TestCode, @"JsonConvert.DeserializeObject(""foo"")"); + var test = string.Format(TestCode, @"JsonConvert.DeserializeObject(""foo"");"); await VerifyCSharpDiagnosticAsync(test, CreateDiagnosticResult(11,51)); } [Fact] public async Task IfDeserializeObjectIdentifierFoundAndJsonTextIsCorrectDoesNotCreatesDiagnostic() { - var test = string.Format(TestCode, @"Newtonsoft.Json.JsonConvert.DeserializeObject(""{""name"":""foo""}"")"); + var test = string.Format(TestCode, @"Newtonsoft.Json.JsonConvert.DeserializeObject(""{""name"":""foo""}"");"); await VerifyCSharpHasNoDiagnosticsAsync(test); } [Fact] public async Task IfAbbreviateDeserializeObjectIdentifierFoundAndJsonTextIsCorrectDoesNotCreatesDiagnostic() { - var test = string.Format(TestCode, @"JsonConvert.DeserializeObject(""{""name"":""foo""}"")"); + var test = string.Format(TestCode, @"JsonConvert.DeserializeObject(""{""name"":""foo""}"");"); await VerifyCSharpHasNoDiagnosticsAsync(test); } [Fact] public async Task IfJObjectParseIdentifierFoundAndJsonTextIsIncorrectCreatesDiagnostic() { - var test = string.Format(TestCode, @"Newtonsoft.Json.Linq.JObject.Parse(""foo"")"); + var test = string.Format(TestCode, @"Newtonsoft.Json.Linq.JObject.Parse(""foo"");"); await VerifyCSharpDiagnosticAsync(test, CreateDiagnosticResult(11, 48)); } [Fact] public async Task IfAbbreviatedJObjectParseIdentifierFoundAndJsonTextIsIncorrectCreatesDiagnostic() { - var test = string.Format(TestCode, @"JObject.Parse(""foo"")"); + var test = string.Format(TestCode, @"JObject.Parse(""foo"");"); await VerifyCSharpDiagnosticAsync(test, CreateDiagnosticResult(11, 27)); } [Fact] public async Task IfJObjectParseIdentifierFoundAndJsonTextIsCorrectDoesNotCreatesDiagnostic() { - var test = string.Format(TestCode, @"JObject.Parse(""{""name"":""foo""}"")"); + var test = string.Format(TestCode, @"JObject.Parse(""{""name"":""foo""}"");"); await VerifyCSharpHasNoDiagnosticsAsync(test); } // [Fact] public async Task IfJArrayParseIdentifierFoundAndJsonTextIsIncorrectCreatesDiagnostic() { - var test = string.Format(TestCode, @"Newtonsoft.Json.Linq.JArray.Parse(""foo"")"); + var test = string.Format(TestCode, @"Newtonsoft.Json.Linq.JArray.Parse(""foo"");"); await VerifyCSharpDiagnosticAsync(test, CreateDiagnosticResult(11, 47)); } [Fact] public async Task IfAbbreviatedJArrayParseIdentifierFoundAndJsonTextIsIncorrectCreatesDiagnostic() { - var test = string.Format(TestCode, @"JArray.Parse(""foo"")"); + var test = string.Format(TestCode, @"JArray.Parse(""foo"");"); await VerifyCSharpDiagnosticAsync(test, CreateDiagnosticResult(11, 26)); } [Fact] public async Task IfJArrayParseIdentifierFoundAndJsonTextIsCorrectDoesNotCreatesDiagnostic() { - var test = string.Format(TestCode, @"JArray.Parse(""{""name"":""foo""}"")"); + var test = string.Format(TestCode, @"JArray.Parse(""{""name"":""foo""}"");"); await VerifyCSharpHasNoDiagnosticsAsync(test); } private static DiagnosticResult CreateDiagnosticResult(int line, int column) { return new DiagnosticResult { Id = DiagnosticId.JsonNet.ToDiagnosticId(), - Message = "Error parsing boolean value. Path '', line 0, position 0.", + Message = "Unexpected end when reading JSON. Path '', line 1, position 3.", Severity = DiagnosticSeverity.Error, Locations = new[] {new DiagnosticResultLocation("Test0.cs", line, column)} }; } - - protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() - { - return new JsonNetAnalyzer(); - } + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() => new JsonNetAnalyzer(); } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs b/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs index eb2775560..6d55294df 100644 --- a/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs @@ -144,7 +144,7 @@ public Person(string name) [Fact] public async Task IgnoreParameters() { - var test = @" + const string test = @" using System; class Foo { diff --git a/test/CSharp/CodeCracker.Test/packages.config b/test/CSharp/CodeCracker.Test/packages.config index 953d54e58..4fe5396c0 100644 --- a/test/CSharp/CodeCracker.Test/packages.config +++ b/test/CSharp/CodeCracker.Test/packages.config @@ -1,14 +1,14 @@  - - + + - + diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index 5ca8c8ccc..2d74ed808 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -35,12 +35,12 @@ 4 - - ..\..\..\packages\FluentAssertions.4.1.0\lib\net45\FluentAssertions.dll + + ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.dll True - - ..\..\..\packages\FluentAssertions.4.1.0\lib\net45\FluentAssertions.Core.dll + + ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.Core.dll True @@ -71,8 +71,8 @@ ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True - - ..\..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True @@ -144,8 +144,8 @@ - - + + diff --git a/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticVerifier.Helper.cs b/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticVerifier.Helper.cs index 81a7cfd79..4a40a1eed 100644 --- a/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticVerifier.Helper.cs +++ b/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticVerifier.Helper.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Threading; using System.Threading.Tasks; namespace CodeCracker.Test diff --git a/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs b/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs index b6cc7416f..5603da4c6 100644 --- a/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs +++ b/test/Common/CodeCracker.Test.Common/Verifiers/CodeFixVerifier.cs @@ -332,8 +332,8 @@ private async static Task VerifyFixAllAsync(string language, DiagnosticAnalyzer /// The codefix to be applied to the code wherever the relevant Diagnostic is found /// C# language version used for compiling the test project, required unless you inform the VB language version. /// The expected number of code actions provided by the code fix. - protected async Task VerifyCSharpHasNumberOfCodeActions(string source, int numberOfCodeActions, CodeFixProvider codeFixProvider = null, LanguageVersion languageVersionCSharp = LanguageVersion.CSharp6) => - await VerifyNumberOfCodeActions(LanguageNames.CSharp, GetDiagnosticAnalyzer(), codeFixProvider ?? GetCodeFixProvider(), source, numberOfCodeActions, languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic14).ConfigureAwait(true); + protected async Task VerifyCSharpHasNumberOfCodeActionsAsync(string source, int numberOfCodeActions, CodeFixProvider codeFixProvider = null, LanguageVersion languageVersionCSharp = LanguageVersion.CSharp6) => + await VerifyNumberOfCodeActionsAsync(LanguageNames.CSharp, GetDiagnosticAnalyzer(), codeFixProvider ?? GetCodeFixProvider(), source, numberOfCodeActions, languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic14).ConfigureAwait(true); /// /// General verifier for a diagnostics that verifies how many code actions a code fix registered. @@ -347,7 +347,7 @@ protected async Task VerifyCSharpHasNumberOfCodeActions(string source, int numbe /// C# language version used for compiling the test project, required unless you inform the VB language version. /// VB language version used for compiling the test project, required unless you inform the C# language version. /// The expected number of code actions provided by the code fix. - private async static Task VerifyNumberOfCodeActions(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string source, int numberOfCodeActions, LanguageVersion languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion languageVersionVB) + private async static Task VerifyNumberOfCodeActionsAsync(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string source, int numberOfCodeActions, LanguageVersion languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion languageVersionVB) { var document = CreateDocument(source, language, languageVersionCSharp, languageVersionVB); var analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzer, new[] { document }).ConfigureAwait(true); diff --git a/test/Common/CodeCracker.Test.Common/packages.config b/test/Common/CodeCracker.Test.Common/packages.config index f1bc5d8d5..30cf43a90 100644 --- a/test/Common/CodeCracker.Test.Common/packages.config +++ b/test/Common/CodeCracker.Test.Common/packages.config @@ -1,8 +1,8 @@  - + - + @@ -11,9 +11,9 @@ - - - + + + diff --git a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj index 9648c8dbb..5243bd27a 100644 --- a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj +++ b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj @@ -54,12 +54,12 @@ On - - ..\..\..\packages\FluentAssertions.4.1.0\lib\net45\FluentAssertions.dll + + ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.dll True - - ..\..\..\packages\FluentAssertions.4.1.0\lib\net45\FluentAssertions.Core.dll + + ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.Core.dll True @@ -82,8 +82,8 @@ ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True - - ..\..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True @@ -184,7 +184,7 @@ - + @@ -229,8 +229,8 @@ - - + + diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index 80a039a2a..d5357ee71 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -184,15 +184,6 @@ Namespace ConsoleApplication1 End Namespace" Await VerifyBasicFixAsync(sourceAssign, fix) End Function - Sub Foo() - Dim v As Boolean - If True Then - ' a comment - v = False - Else - v = True - End If - End Sub Public Async Function WhenUsingIfAndElseWithAssignmentChangeToTernaryFixAll() As Task diff --git a/test/VisualBasic/CodeCracker.Test/Usage/JsonNetTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb similarity index 96% rename from test/VisualBasic/CodeCracker.Test/Usage/JsonNetTests.vb rename to test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb index ea69e25a7..a1b921ef7 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/JsonNetTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb @@ -3,7 +3,7 @@ Imports Microsoft.CodeAnalysis.Diagnostics Imports Xunit Namespace Usage - Public Class JsonNetTests + Public Class JsonNetAnalyzerTests Inherits CodeFixVerifier Private Const TestCode = " @@ -21,7 +21,7 @@ End Namespace" Private Shared Function CreateDiagnosticResult(line As Integer, column As Integer) As DiagnosticResult Return New DiagnosticResult With { .Id = DiagnosticId.JsonNet.ToDiagnosticId(), - .Message = "Error parsing boolean value. Path '', line 0, position 0.", + .Message = "Unexpected end when reading JSON. Path '', line 1, position 3.", .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Error, .Locations = {New DiagnosticResultLocation("Test0.vb", line, column)} } diff --git a/test/VisualBasic/CodeCracker.Test/packages.config b/test/VisualBasic/CodeCracker.Test/packages.config index 2739aafad..5e32c07e9 100644 --- a/test/VisualBasic/CodeCracker.Test/packages.config +++ b/test/VisualBasic/CodeCracker.Test/packages.config @@ -1,14 +1,14 @@  - - + + - + From cbc32b0c621b0ad4a73d88df0a32e26c442dea6d Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 16 Apr 2016 17:01:06 -0300 Subject: [PATCH 045/234] Update Microsoft.CodeAnalysis.Analyzers to 1.1.0 This had to be done manually, as the other CodeAnalysis packages depend on version =1.0.0 of Microsoft.CodeAnalysis.Analyzers, so, if using VS to do this, it will auto upgrade all Microsoft.CodeAnalysis.* packages to 1.1.0 as well, which will keep the analyzer from working on VS 2015 RTM, only working on Update 1. --- src/CSharp/CodeCracker/CodeCracker.csproj | 4 ++-- src/CSharp/CodeCracker/packages.config | 2 +- src/Common/CodeCracker.Common/CodeCracker.Common.csproj | 4 ++-- src/Common/CodeCracker.Common/packages.config | 2 +- src/VisualBasic/CodeCracker/CodeCracker.vbproj | 4 ++-- src/VisualBasic/CodeCracker/packages.config | 2 +- test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj | 4 ++-- test/CSharp/CodeCracker.Test/packages.config | 2 +- .../CodeCracker.Test.Common/CodeCracker.Test.Common.csproj | 4 ++-- test/Common/CodeCracker.Test.Common/packages.config | 2 +- test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj | 4 ++-- test/VisualBasic/CodeCracker.Test/packages.config | 2 +- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index e8c815a5f..e1a60a05e 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -223,8 +223,8 @@ - - + + diff --git a/src/CSharp/CodeCracker/packages.config b/src/CSharp/CodeCracker/packages.config index 442f37a31..26624b6d1 100644 --- a/src/CSharp/CodeCracker/packages.config +++ b/src/CSharp/CodeCracker/packages.config @@ -1,7 +1,7 @@  - + diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index 1ea38b03f..6ecee6f01 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -72,8 +72,8 @@ - - + + diff --git a/src/Common/CodeCracker.Common/packages.config b/src/Common/CodeCracker.Common/packages.config index 0265a0254..564e6399a 100644 --- a/src/Common/CodeCracker.Common/packages.config +++ b/src/Common/CodeCracker.Common/packages.config @@ -1,7 +1,7 @@  - + diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index 5fe35f007..ba1b36a08 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -164,8 +164,8 @@ - - + + diff --git a/src/VisualBasic/CodeCracker/packages.config b/src/VisualBasic/CodeCracker/packages.config index 30ff459a2..06a0521ef 100644 --- a/src/VisualBasic/CodeCracker/packages.config +++ b/src/VisualBasic/CodeCracker/packages.config @@ -1,7 +1,7 @@  - + diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index f474e4208..b17ba4a79 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -237,8 +237,8 @@ - - + + diff --git a/test/CSharp/CodeCracker.Test/packages.config b/test/CSharp/CodeCracker.Test/packages.config index 4fe5396c0..2796290c0 100644 --- a/test/CSharp/CodeCracker.Test/packages.config +++ b/test/CSharp/CodeCracker.Test/packages.config @@ -2,7 +2,7 @@ - + diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index 2d74ed808..bf88cd107 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -146,8 +146,8 @@ - - + + diff --git a/test/Common/CodeCracker.Test.Common/packages.config b/test/Common/CodeCracker.Test.Common/packages.config index 30cf43a90..9f3abe748 100644 --- a/test/Common/CodeCracker.Test.Common/packages.config +++ b/test/Common/CodeCracker.Test.Common/packages.config @@ -3,7 +3,7 @@ - + diff --git a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj index 5243bd27a..96671272a 100644 --- a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj +++ b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj @@ -231,8 +231,8 @@ - - + + diff --git a/test/VisualBasic/CodeCracker.Test/packages.config b/test/VisualBasic/CodeCracker.Test/packages.config index 5e32c07e9..784240f28 100644 --- a/test/VisualBasic/CodeCracker.Test/packages.config +++ b/test/VisualBasic/CodeCracker.Test/packages.config @@ -2,7 +2,7 @@ - + From 9bb6062cfc426c3b2cc4ae0606241caecb2233b2 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 17 Apr 2016 02:00:28 -0300 Subject: [PATCH 046/234] Bump version to 1.0.1 --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CSharp/CodeCracker/Properties/AssemblyInfo.cs | 2 +- src/CodeCracker.nuspec | 6 +++--- src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 2 +- src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb | 2 +- test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Test.Common/Properties/AssemblyInfo.cs | 2 +- .../VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index ceaef7c59..19b4ff34c 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for C# An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index bd9ae7cc4..f659d5f96 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.CSharp - 1.0.0 + 1.0.1 CodeCracker for C# giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs index 0b5e5b22a..e73618076 100644 --- a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.14")] +[assembly: AssemblyFileVersion("1.0.1.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index 67e27ad9d..c910e7aba 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker - 1.0.0 + 1.0.1 CodeCracker for C# and VB giggio,elemarjr,carloscds giggio,elemarjr,carloscds @@ -19,8 +19,8 @@ This is a community project, free and open source. Everyone is invited to contri Copyright CodeCracker 2014-2016 roslyn, analyzers - - + + diff --git a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs index 266a6438b..8fd31cfbe 100644 --- a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs +++ b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs @@ -14,6 +14,6 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.14")] +[assembly: AssemblyFileVersion("1.0.1.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] [assembly: InternalsVisibleTo("CodeCracker.Test.VisualBasic")] \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index 3cfea306c..2292f0dec 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for Visual Basic An analyzer library for VB that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index 3be6daa7e..70abb04ba 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.VisualBasic - 1.0.0 + 1.0.1 CodeCracker for Visual Basic giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb index e1f2b3667..9f6f2650c 100644 --- a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb +++ b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb @@ -14,5 +14,5 @@ Imports System.Runtime.InteropServices - + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs index 71eb11924..9da58a97d 100644 --- a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs +++ b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.14")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs index 587387784..8c492b358 100644 --- a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en-us")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.14")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb index b5de9452d..2599bd9f5 100644 --- a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb +++ b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb @@ -14,4 +14,4 @@ Imports System.Runtime.InteropServices - \ No newline at end of file + \ No newline at end of file From cb56328511b10200992cba78d3f07dcaa1e34638 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 17 Apr 2016 02:07:17 -0300 Subject: [PATCH 047/234] Fixes CallExtensionMethodAsExtensionAnalyzer with C# 5 Closes #781 Also allows for same tree extension methods to be detected by comparing by method name instead of symbol equality. --- .../CallExtensionMethodAsExtensionAnalyzer.cs | 11 ++-- .../CallExtensionMethodAsExtensionTests.cs | 54 ++++++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs b/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs index 15d9bff32..e949222bd 100644 --- a/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs @@ -66,12 +66,15 @@ private static bool IsSelectingADifferentMethod(IEnumerable childNod var speculativeRootWithExtensionMethod = tree.GetCompilationUnitRoot() .ReplaceNode(invocationExpression, newInvocationStatement) .AddUsings(extensionMethodNamespaceUsingDirective); - var speculativeModel = compilation.ReplaceSyntaxTree(tree, speculativeRootWithExtensionMethod.SyntaxTree) - .GetSemanticModel(speculativeRootWithExtensionMethod.SyntaxTree); - var speculativeInvocationStatement = speculativeRootWithExtensionMethod.SyntaxTree.GetCompilationUnitRoot().GetAnnotatedNodes(introduceExtensionMethodAnnotation).Single() as InvocationExpressionSyntax; + var speculativeTree = speculativeRootWithExtensionMethod.SyntaxTree; + var speculativeTreeOptions = (CSharpParseOptions)speculativeTree.Options; + var speculativeTreeWithCorrectLanguageVersion = speculativeTree.WithRootAndOptions(speculativeRootWithExtensionMethod, speculativeTreeOptions.WithLanguageVersion(((CSharpParseOptions)tree.Options).LanguageVersion)); + var speculativeModel = compilation.ReplaceSyntaxTree(tree, speculativeTreeWithCorrectLanguageVersion) + .GetSemanticModel(speculativeTreeWithCorrectLanguageVersion); + var speculativeInvocationStatement = speculativeTreeWithCorrectLanguageVersion.GetCompilationUnitRoot().GetAnnotatedNodes(introduceExtensionMethodAnnotation).Single() as InvocationExpressionSyntax; var speculativeExtensionMethodSymbol = speculativeModel.GetSymbolInfo(speculativeInvocationStatement.Expression).Symbol as IMethodSymbol; var speculativeNonExtensionFormOfTheMethodSymbol = speculativeExtensionMethodSymbol?.GetConstructedReducedFrom(); - return speculativeNonExtensionFormOfTheMethodSymbol == null || !speculativeNonExtensionFormOfTheMethodSymbol.Equals(methodSymbol); + return speculativeNonExtensionFormOfTheMethodSymbol == null || speculativeNonExtensionFormOfTheMethodSymbol.ToString() != methodSymbol.ToString();//can't compare equality, as speculative symbol might be different } private static int CountArguments(IEnumerable childNodes) => diff --git a/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs b/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs index d951964ae..2b7e06964 100644 --- a/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using System.Threading.Tasks; using Xunit; @@ -28,7 +29,7 @@ public void Bar() } [Fact] - public async Task WhenCallExtensionMethodAsStaticMenthodTriggerAFix() + public async Task WhenCallExtensionMethodAsStaticMethodTriggerAFix() { const string source = @" using System.Linq; @@ -55,6 +56,57 @@ public void Bar() await VerifyCSharpDiagnosticAsync(source, expected); } + [Fact] + public async Task WhenCallExtensionMethodAsStaticMethodTriggerAFixWithCSharp5() + { + const string source = @" + using System.Linq; + namespace ConsoleApplication1 + { + public class Foo + { + public void Bar() + { + var source = new int[] { 1, 2, 3 }; + Enumerable.Any(source, x => x > 1); + } + } + }"; + var expected = new DiagnosticResult + { + Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), + Message = "Do not call 'Any' method of class 'Enumerable' as a static method", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 33) } + }; + await VerifyCSharpDiagnosticAsync(source, expected, LanguageVersion.CSharp5); + } + + [Fact] + public async Task CreatesDiagnosticWhenExtensionClassInSameTree() + { + const string source = @" +class Foo +{ + public static void Bar() + { + C.M(""""); + } +} +public static class C +{ + public static string M(this string s) => s; +}"; + var expected = new DiagnosticResult + { + Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), + Message = "Do not call 'M' method of class 'C' as a static method", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 9) } + }; + await VerifyCSharpDiagnosticAsync(source, expected, LanguageVersion.CSharp5); + } + [Fact] public async Task WhenCallExtensionMethodWithFullNamespaceAsStaticMenthodTriggerAFix() { From a657cab4893859e00571d0cf658acf283e948751 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 17 Apr 2016 02:23:01 -0300 Subject: [PATCH 048/234] Change build and deployment conditions Allow now build from tags. Deploy now from tags not from the release branch anymore. For patches, now deploy to myget any branch that looks like a version number, like: v1.0.x v3.9.x Always ending with an `x`. --- appveyor.yml | 11 ++++++++--- build.targets.ps1 | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c89ed6dff..58c443b5b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,5 @@ version: 1.0.0.{build} -skip_tags: true - configuration: ReleaseNoVsix init: @@ -56,7 +54,7 @@ deploy: secure: s1aIT1sGbIeG5Ccgree7K+k/h7LOSzPfJOrsWcCuzgFGrcuexPZUwX/CfYnU9w4v skip_symbols: true on: - branch: release + appveyor_repo_tag: true - provider: NuGet server: https://www.myget.org/F/codecrackerbuild/api/v2/package api_key: @@ -71,6 +69,13 @@ deploy: skip_symbols: true on: branch: vnext +- provider: NuGet + server: https://www.myget.org/F/codecrackerbuild/api/v2/package + api_key: + secure: 42eslsnaZIIcMVVaeC9Qu5NI9yjzLzHWYUGl0HLhl0YurivQezpMyJOwgSVjiGmj + skip_symbols: true + on: + branch: /v\d\.\d\.x/ notifications: - provider: Email diff --git a/build.targets.ps1 b/build.targets.ps1 index 7c7e12a6a..42ee817bb 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -26,7 +26,7 @@ Properties { $reportGeneratorExe = "$packagesDir\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe" $coverageReportDir = "$logDir\codecoverage\" $coverallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" - $isRelease = $isAppVeyor -and ($env:APPVEYOR_REPO_BRANCH -eq "release") + $isRelease = $isAppVeyor -and (($env:APPVEYOR_REPO_BRANCH -eq "release") -or ($env:APPVEYOR_REPO_TAG -eq "true")) $isPullRequest = $env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null } From b38cef381242f3f2306e4e2317ff54a58b368b13 Mon Sep 17 00:00:00 2001 From: ngobzin11 Date: Wed, 20 Apr 2016 14:51:35 -0500 Subject: [PATCH 049/234] Restricted ReadonlyFieldAnalyzer to primitive and reference types, #775 --- .../Usage/ReadonlyFieldAnalyzer.cs | 15 ++- .../Usage/ReadonlyFieldTests.cs | 95 +++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index 97d3ebd64..6c031eebd 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -145,8 +145,12 @@ private static Dictionary GetCandidateVa private static Dictionary GetCandidateVariables(SemanticModel semanticModel, FieldDeclarationSyntax fieldDeclaration) { var variablesToMakeReadonly = new Dictionary(); - if (fieldDeclaration == null) return variablesToMakeReadonly; - if (!CanBeMadeReadonly(fieldDeclaration)) return variablesToMakeReadonly; + if (fieldDeclaration == null || + IsComplexValueType(semanticModel, fieldDeclaration) || + !CanBeMadeReadonly(fieldDeclaration)) + { + return variablesToMakeReadonly; + } foreach (var variable in fieldDeclaration.Declaration.Variables) { if (variable.Initializer == null) continue; @@ -167,6 +171,13 @@ private static bool CanBeMadeReadonly(FieldDeclarationSyntax fieldDeclaration) || m.IsKind(SyntaxKind.ConstKeyword)); } + private static bool IsComplexValueType(SemanticModel semanticModel, FieldDeclarationSyntax fieldDeclaration) + { + var fieldTypeName = fieldDeclaration.Declaration.Type; + var fieldType = semanticModel.GetTypeInfo(fieldTypeName).ConvertedType; + return fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + } + private static bool CanBeMadeReadonly(IFieldSymbol fieldSymbol) { return (fieldSymbol.DeclaredAccessibility == Accessibility.NotApplicable diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index b7fb708b6..bd528508c 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -846,5 +846,100 @@ static void B() }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } + + [Fact] + public async Task UserDefinedStructFieldDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct = default(MyStruct); + + private struct MyStruct + { + public int Value; + } + } + } + "; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DateTimeFieldInitializedOnDeclarationDoesNotCreateDiagnostic() + { + const string source = @" + using System; + + namespace ConsoleApplication1 + { + public class MyClass + { + private DateTime date = new DateTime(2008, 5, 1, 8, 30, 52); + } + } + "; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task EnumerationFieldInitializedOnDeclarationCreatesADiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private VehicleType car = VehicleType.Car; + + private enum VehicleType + { + None = 0, + Car = 1, + Truck = 2 + } + } + } + "; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), + Message = string.Format(ReadonlyFieldAnalyzer.Message, "car"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 33) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task ReferenceTypeFieldInitializedInConstructorCreatesADiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class Person + { + private string name; + + public Person(string name) + { + this.name = name; + } + } + } + "; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), + Message = string.Format(ReadonlyFieldAnalyzer.Message, "name"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 28) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } } } From 0e2adc07c7de3eabed62e82dba60d715d434cc4f Mon Sep 17 00:00:00 2001 From: Hubert Kindermann Date: Tue, 28 Jun 2016 16:49:48 +0200 Subject: [PATCH 050/234] Fixes #773. --- .../CSharpGeneratedCodeAnalysisExtensions.cs | 14 ++-- .../GeneratedCodeAnalysisExtensionsTests.cs | 77 ++++++++----------- 2 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs index d7386b3c5..339e64ae1 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs @@ -1,8 +1,8 @@ using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using System.Linq; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.CSharp; namespace CodeCracker { @@ -48,9 +48,13 @@ public static bool HasAutoGeneratedComment(this SyntaxTree tree) if (!firstToken.HasLeadingTrivia) return false; trivia = firstToken.LeadingTrivia; } - var commentLines = trivia.Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia)).Take(2).ToList(); - if (commentLines.Count != 2) return false; - return commentLines[1].ToString() == "// "; + + var comments = trivia.Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia) || t.IsKind(SyntaxKind.MultiLineCommentTrivia)); + return comments.Any(t => + { + var s = t.ToString(); + return s.Contains(" GetSymbolAnalysisContext(source).IsGenerated().Should().BeTrue(); - [Fact] - public static void SyntaxNodeAnalysis_WithAutoGeneratedCommentBasedOnWebForms() => - GetSyntaxNodeAnalysisContext( + [Theory] + [InlineData( @"//------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -304,11 +303,8 @@ namespace WebApplication3 public partial class _Default { } -}").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SyntaxTreeAnalysis_WithAutoGeneratedCommentBasedOnWebForms() => - GetSyntaxTreeAnalysisContext( +}", false)] + [InlineData( @"//------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -316,57 +312,46 @@ public static void SyntaxTreeAnalysis_WithAutoGeneratedCommentBasedOnWebForms() // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // -//------------------------------------------------------------------------------ - +//------------------------------------------------------------------------------", true)] + [InlineData( +@"// +// This code was generated by a tool. namespace WebApplication3 { public partial class _Default { } -}").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SyntaxTreeAnalysis_WithAutoGeneratedCommentEmpty() => - GetSyntaxTreeAnalysisContext( -@"//------------------------------------------------------------------------------ -// -// This code was generated by a tool. +}", false)] + [InlineData( +@"// +// This code was generated by a tool.", true)] + [InlineData( +@"// This code was generated by a tool. // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SymbolicAnalysis_WithAutoGeneratedCommentBasedOnWebForms() => - GetSymbolAnalysisContext( -@"//------------------------------------------------------------------------------ // -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - namespace WebApplication3 { public partial class _Default { } -}").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SyntaxNodeAnalysis_WithAutoGeneratedCommentEmpty() => - GetSyntaxNodeAnalysisContext( -@"//------------------------------------------------------------------------------ -// -// This code was generated by a tool. +}", false)] + [InlineData( +@"// This code was generated by a tool. // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------").IsGenerated().Should().BeTrue(); +// ", true)] + public static void SyntaxNodeAnalysis_WithAutoGeneratedComment(string source, bool isEmpty) + { + GetSyntaxTreeAnalysisContext(source).IsGenerated().Should().BeTrue(); + if (isEmpty) + { + GetSyntaxNodeAnalysisContext(source).IsGenerated().Should().BeTrue(); + } + else + { + GetSyntaxNodeAnalysisContext(source).IsGenerated().Should().BeTrue(); + GetSymbolAnalysisContext(source).IsGenerated().Should().BeTrue(); + } + } private static SyntaxNodeAnalysisContext GetSyntaxNodeAnalysisContext(string code, string fileName = baseProjectPath + "a.cs") => GetSyntaxNodeAnalysisContext(code, fileName); From 0af060616a99c4b2dd223ca728cacfb277cf07c9 Mon Sep 17 00:00:00 2001 From: ngobzin11 Date: Wed, 20 Apr 2016 14:51:35 -0500 Subject: [PATCH 051/234] Restricted ReadonlyFieldAnalyzer to primitive and reference types, #775 --- .../Usage/ReadonlyFieldAnalyzer.cs | 15 ++- .../Usage/ReadonlyFieldTests.cs | 95 +++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index 97d3ebd64..6c031eebd 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -145,8 +145,12 @@ private static Dictionary GetCandidateVa private static Dictionary GetCandidateVariables(SemanticModel semanticModel, FieldDeclarationSyntax fieldDeclaration) { var variablesToMakeReadonly = new Dictionary(); - if (fieldDeclaration == null) return variablesToMakeReadonly; - if (!CanBeMadeReadonly(fieldDeclaration)) return variablesToMakeReadonly; + if (fieldDeclaration == null || + IsComplexValueType(semanticModel, fieldDeclaration) || + !CanBeMadeReadonly(fieldDeclaration)) + { + return variablesToMakeReadonly; + } foreach (var variable in fieldDeclaration.Declaration.Variables) { if (variable.Initializer == null) continue; @@ -167,6 +171,13 @@ private static bool CanBeMadeReadonly(FieldDeclarationSyntax fieldDeclaration) || m.IsKind(SyntaxKind.ConstKeyword)); } + private static bool IsComplexValueType(SemanticModel semanticModel, FieldDeclarationSyntax fieldDeclaration) + { + var fieldTypeName = fieldDeclaration.Declaration.Type; + var fieldType = semanticModel.GetTypeInfo(fieldTypeName).ConvertedType; + return fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + } + private static bool CanBeMadeReadonly(IFieldSymbol fieldSymbol) { return (fieldSymbol.DeclaredAccessibility == Accessibility.NotApplicable diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index b7fb708b6..bd528508c 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -846,5 +846,100 @@ static void B() }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } + + [Fact] + public async Task UserDefinedStructFieldDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct = default(MyStruct); + + private struct MyStruct + { + public int Value; + } + } + } + "; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DateTimeFieldInitializedOnDeclarationDoesNotCreateDiagnostic() + { + const string source = @" + using System; + + namespace ConsoleApplication1 + { + public class MyClass + { + private DateTime date = new DateTime(2008, 5, 1, 8, 30, 52); + } + } + "; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task EnumerationFieldInitializedOnDeclarationCreatesADiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private VehicleType car = VehicleType.Car; + + private enum VehicleType + { + None = 0, + Car = 1, + Truck = 2 + } + } + } + "; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), + Message = string.Format(ReadonlyFieldAnalyzer.Message, "car"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 33) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task ReferenceTypeFieldInitializedInConstructorCreatesADiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class Person + { + private string name; + + public Person(string name) + { + this.name = name; + } + } + } + "; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), + Message = string.Format(ReadonlyFieldAnalyzer.Message, "name"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 28) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } } } From f7d2893e8ea03ace30451a553a00f80615553987 Mon Sep 17 00:00:00 2001 From: Hubert Kindermann Date: Tue, 28 Jun 2016 16:49:48 +0200 Subject: [PATCH 052/234] Fixes #773. --- .../CSharpGeneratedCodeAnalysisExtensions.cs | 14 ++-- .../GeneratedCodeAnalysisExtensionsTests.cs | 77 ++++++++----------- 2 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs index d7386b3c5..339e64ae1 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpGeneratedCodeAnalysisExtensions.cs @@ -1,8 +1,8 @@ using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using System.Linq; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.CSharp; namespace CodeCracker { @@ -48,9 +48,13 @@ public static bool HasAutoGeneratedComment(this SyntaxTree tree) if (!firstToken.HasLeadingTrivia) return false; trivia = firstToken.LeadingTrivia; } - var commentLines = trivia.Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia)).Take(2).ToList(); - if (commentLines.Count != 2) return false; - return commentLines[1].ToString() == "// "; + + var comments = trivia.Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia) || t.IsKind(SyntaxKind.MultiLineCommentTrivia)); + return comments.Any(t => + { + var s = t.ToString(); + return s.Contains(" GetSymbolAnalysisContext(source).IsGenerated().Should().BeTrue(); - [Fact] - public static void SyntaxNodeAnalysis_WithAutoGeneratedCommentBasedOnWebForms() => - GetSyntaxNodeAnalysisContext( + [Theory] + [InlineData( @"//------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -304,11 +303,8 @@ namespace WebApplication3 public partial class _Default { } -}").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SyntaxTreeAnalysis_WithAutoGeneratedCommentBasedOnWebForms() => - GetSyntaxTreeAnalysisContext( +}", false)] + [InlineData( @"//------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -316,57 +312,46 @@ public static void SyntaxTreeAnalysis_WithAutoGeneratedCommentBasedOnWebForms() // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // -//------------------------------------------------------------------------------ - +//------------------------------------------------------------------------------", true)] + [InlineData( +@"// +// This code was generated by a tool. namespace WebApplication3 { public partial class _Default { } -}").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SyntaxTreeAnalysis_WithAutoGeneratedCommentEmpty() => - GetSyntaxTreeAnalysisContext( -@"//------------------------------------------------------------------------------ -// -// This code was generated by a tool. +}", false)] + [InlineData( +@"// +// This code was generated by a tool.", true)] + [InlineData( +@"// This code was generated by a tool. // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SymbolicAnalysis_WithAutoGeneratedCommentBasedOnWebForms() => - GetSymbolAnalysisContext( -@"//------------------------------------------------------------------------------ // -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - namespace WebApplication3 { public partial class _Default { } -}").IsGenerated().Should().BeTrue(); - - [Fact] - public static void SyntaxNodeAnalysis_WithAutoGeneratedCommentEmpty() => - GetSyntaxNodeAnalysisContext( -@"//------------------------------------------------------------------------------ -// -// This code was generated by a tool. +}", false)] + [InlineData( +@"// This code was generated by a tool. // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------").IsGenerated().Should().BeTrue(); +// ", true)] + public static void SyntaxNodeAnalysis_WithAutoGeneratedComment(string source, bool isEmpty) + { + GetSyntaxTreeAnalysisContext(source).IsGenerated().Should().BeTrue(); + if (isEmpty) + { + GetSyntaxNodeAnalysisContext(source).IsGenerated().Should().BeTrue(); + } + else + { + GetSyntaxNodeAnalysisContext(source).IsGenerated().Should().BeTrue(); + GetSymbolAnalysisContext(source).IsGenerated().Should().BeTrue(); + } + } private static SyntaxNodeAnalysisContext GetSyntaxNodeAnalysisContext(string code, string fileName = baseProjectPath + "a.cs") => GetSyntaxNodeAnalysisContext(code, fileName); From 794c05aaedd35f207c6bc9e6c327d0c2df967f36 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 7 Aug 2016 16:22:57 -0300 Subject: [PATCH 053/234] Bump version to 1.1.0 --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CSharp/CodeCracker/Properties/AssemblyInfo.cs | 2 +- src/CodeCracker.nuspec | 6 +++--- src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 2 +- src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb | 2 +- test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Test.Common/Properties/AssemblyInfo.cs | 2 +- .../VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index 19b4ff34c..3a3f50bbe 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for C# An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index f659d5f96..72744d97a 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.CSharp - 1.0.1 + 1.1.0 CodeCracker for C# giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs index e73618076..f63d51c3e 100644 --- a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index c910e7aba..f5113b83b 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker - 1.0.1 + 1.1.0 CodeCracker for C# and VB giggio,elemarjr,carloscds giggio,elemarjr,carloscds @@ -19,8 +19,8 @@ This is a community project, free and open source. Everyone is invited to contri Copyright CodeCracker 2014-2016 roslyn, analyzers - - + + diff --git a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs index 8fd31cfbe..b57f8b71e 100644 --- a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs +++ b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs @@ -14,6 +14,6 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] [assembly: InternalsVisibleTo("CodeCracker.Test.VisualBasic")] \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index 2292f0dec..6cff126bc 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for Visual Basic An analyzer library for VB that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index 70abb04ba..326c5ccb4 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.VisualBasic - 1.0.1 + 1.1.0 CodeCracker for Visual Basic giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb index 9f6f2650c..0758c2287 100644 --- a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb +++ b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb @@ -14,5 +14,5 @@ Imports System.Runtime.InteropServices - + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs index 9da58a97d..4b18b5a68 100644 --- a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs +++ b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.1.0.0")] \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs index 8c492b358..d56074edd 100644 --- a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en-us")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.1.0.0")] \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb index 2599bd9f5..8823e3c6f 100644 --- a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb +++ b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb @@ -14,4 +14,4 @@ Imports System.Runtime.InteropServices - \ No newline at end of file + \ No newline at end of file From 553d402d555144de13a35085f81d3b2f5f2e7229 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 8 Aug 2016 00:07:39 -0300 Subject: [PATCH 054/234] Enhance UseInvokeMethodToFireEventAnalyzer to detect null checks Closes #779 --- .../UseInvokeMethodToFireEventAnalyzer.cs | 48 +++++++++++++------ .../Design/UseInvokeMethodToFireEventTests.cs | 41 ++++++++++++++++ 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs index c0d8ef201..1ae8992d4 100644 --- a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs @@ -52,6 +52,9 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (HasCheckForNullThatReturns(invocation, context.SemanticModel, symbol)) return; if (IsInsideANullCheck(invocation, context.SemanticModel, symbol)) return; + if (IsPartOfATernaryThatChecksForNull(invocation, context.SemanticModel, symbol)) return; + if (IsPartOfALogicalOrThatChecksForNull(invocation, context.SemanticModel, symbol)) return; + if (IsPartOfALogicalAndThatChecksForNotNull(invocation, context.SemanticModel, symbol)) return; if (symbol.IsReadOnlyAndInitializedForCertain(context)) return; context.ReportDiagnostic(Diagnostic.Create(Rule, invocation.GetLocation(), identifier.Identifier.Text)); @@ -91,22 +94,37 @@ private static bool HasCheckForNullThatReturns(InvocationExpressionSyntax invoca return false; } - private static bool IsInsideANullCheck(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) + private static bool IsPartOfATernaryThatChecksForNull(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) => + IsConditionThatChecksForNotEqualsNull(invocation.FirstAncestorOfType()?.Condition, semanticModel, symbol); + + private static bool IsPartOfALogicalOrThatChecksForNull(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) => + IsConditionThatChecksForEqualsNull(invocation.FirstAncestorOfKind(SyntaxKind.LogicalOrExpression)?.Left, semanticModel, symbol); + + private static bool IsPartOfALogicalAndThatChecksForNotNull(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) => + IsConditionThatChecksForNotEqualsNull(invocation.FirstAncestorOfKind(SyntaxKind.LogicalAndExpression)?.Left, semanticModel, symbol); + + private static bool IsInsideANullCheck(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) => + invocation.Ancestors().OfType().Any(@if => IsConditionThatChecksForNotEqualsNull(@if.Condition, semanticModel, symbol)); + + private static bool IsConditionThatChecksForNotEqualsNull(ExpressionSyntax condition, SemanticModel semanticModel, ISymbol symbol) => + IsConditionThatChecksForNull(condition, semanticModel, symbol, SyntaxKind.NotEqualsExpression); + + private static bool IsConditionThatChecksForEqualsNull(ExpressionSyntax condition, SemanticModel semanticModel, ISymbol symbol) => + IsConditionThatChecksForNull(condition, semanticModel, symbol, SyntaxKind.EqualsExpression); + + private static bool IsConditionThatChecksForNull(ExpressionSyntax condition, SemanticModel semanticModel, ISymbol symbol, SyntaxKind binarySyntaxKind) { - var ifs = invocation.Ancestors().OfType(); - foreach (IfStatementSyntax @if in ifs) - { - if (!@if.Condition?.IsKind(SyntaxKind.NotEqualsExpression) ?? true) continue; - var equals = (BinaryExpressionSyntax)@if.Condition; - if (equals.Left == null || equals.Right == null) continue; - ISymbol identifierSymbol; - if (equals.Right.IsKind(SyntaxKind.NullLiteralExpression) && equals.Left.IsKind(SyntaxKind.IdentifierName)) - identifierSymbol = semanticModel.GetSymbolInfo(equals.Left).Symbol; - else if (equals.Left.IsKind(SyntaxKind.NullLiteralExpression) && equals.Right.IsKind(SyntaxKind.IdentifierName)) - identifierSymbol = semanticModel.GetSymbolInfo(equals.Right).Symbol; - else continue; - if (symbol.Equals(identifierSymbol)) return true; - } + if (condition == null) return false; + if (!condition.IsKind(binarySyntaxKind)) return false; + var equals = (BinaryExpressionSyntax)condition; + if (equals.Left == null || equals.Right == null) return false; + ISymbol identifierSymbol; + if (equals.Right.IsKind(SyntaxKind.NullLiteralExpression) && equals.Left.IsKind(SyntaxKind.IdentifierName)) + identifierSymbol = semanticModel.GetSymbolInfo(equals.Left).Symbol; + else if (equals.Left.IsKind(SyntaxKind.NullLiteralExpression) && equals.Right.IsKind(SyntaxKind.IdentifierName)) + identifierSymbol = semanticModel.GetSymbolInfo(equals.Right).Symbol; + else return false; + if (symbol.Equals(identifierSymbol)) return true; return false; } } diff --git a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs index 9f3239e43..0ff013093 100644 --- a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs @@ -1096,5 +1096,46 @@ public void Execute() await VerifyCSharpHasNoDiagnosticsAsync(test); } + + [Fact] + public async void IgnoreIfAlreadyCheckedForNull() + { + const string test = @" +public static int Get(Func method) { + return method != null ? method(12345) : 0; +}"; + + await VerifyCSharpHasNoDiagnosticsAsync(test.WrapInCSharpClass()); + } + + [Fact] + public async void IgnoreIfInLogicalOrThatCheckedForNull() + { + const string test = @" +public class Foo +{ + private System.Func _filter; + public void Bar() + { + var b = _filter == null || _filter(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(test.WrapInCSharpClass()); + } + + [Fact] + public async void IgnoreIfInLogicalAndThatCheckedForNotNull() + { + const string test = @" +public class Foo +{ + private System.Func _filter; + public void Bar() + { + var b = _filter != null && _filter(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(test.WrapInCSharpClass()); + } } } \ No newline at end of file From 61545d9b28e8c56b862765e5135acc15b1823733 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 9 Aug 2016 00:56:09 -0300 Subject: [PATCH 055/234] Fix CallExtensionMethodAsExtensionAnalyzer for methods without arguments Fixes #810 --- .../CallExtensionMethodAsExtensionAnalyzer.cs | 1 + .../CallExtensionMethodAsExtensionTests.cs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs b/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs index e949222bd..0a6f14de5 100644 --- a/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/CallExtensionMethodAsExtensionAnalyzer.cs @@ -46,6 +46,7 @@ private static void AnalyzeInvocation(SyntaxNodeAnalysisContext context, Compila var methodCaller = childNodes.OfType().FirstOrDefault(); if (methodCaller == null) return; var argumentsCount = CountArguments(childNodes); + if (argumentsCount == 0) return; var classSymbol = GetCallerClassSymbol(context.SemanticModel, methodCaller.Expression); if (classSymbol == null || !classSymbol.MightContainExtensionMethods) return; var methodSymbol = GetCallerMethodSymbol(context.SemanticModel, methodCaller.Name, argumentsCount); diff --git a/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs b/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs index 2b7e06964..31de8f5c7 100644 --- a/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs @@ -9,6 +9,25 @@ namespace CodeCracker.Test.CSharp.Usage public class CallExtensionMethodAsExtensionTests : CodeFixVerifier { + [Fact] + public async Task IgnoreWhenMissingArguments() + { + const string source = @" +using System.Linq; +class Foo +{ + public static void N() + { + Exts.M(); + } +} +static class Exts +{ + public static void M(this string s) => s.ToString(); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task WhenCallExtensionMethodAsExtensionHasNoDiagnostics() { From bb44e97d90562093d648ff70d97f9104b6c37719 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 9 Aug 2016 01:15:11 -0300 Subject: [PATCH 056/234] Remove ref and out from conditions that allow read only fields Fixes #788 --- .../Usage/ReadonlyFieldAnalyzer.cs | 7 +++++ .../Usage/ReadonlyFieldTests.cs | 28 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index 6c031eebd..401e7ef48 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -59,6 +59,13 @@ private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation c ? semanticModel : compilation.GetSemanticModel(syntaxReference.SyntaxTree); var descendants = syntaxReference.GetSyntax().DescendantNodes().ToList(); + var argsWithRefOrOut = descendants.OfType().Where(a => a.RefOrOutKeyword != null); + foreach (var argWithRefOrOut in argsWithRefOrOut) + { + var fieldSymbol = syntaxRefSemanticModel.GetSymbolInfo(argWithRefOrOut.Expression).Symbol as IFieldSymbol; + if (fieldSymbol == null) continue; + variablesToMakeReadonly.Remove(fieldSymbol); + } var assignments = descendants.OfKind(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression, SyntaxKind.AndAssignmentExpression, SyntaxKind.DivideAssignmentExpression, SyntaxKind.ExclusiveOrAssignmentExpression, SyntaxKind.LeftShiftAssignmentExpression, SyntaxKind.ModuloAssignmentExpression, diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index bd528508c..efbaa8c12 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -19,6 +19,32 @@ class TypeName await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); } + [Fact] + public async Task IgnoreOut() + { + const string source = @" +public class C +{ + private string field = ""; + private static void Foo(out string bar) => bar = ""; + public void Baz() => Foo(out field); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task IgnoreRef() + { + const string source = @" +public class C +{ + private string field = ""; + private static void Foo(ref string bar) => bar = ""; + public void Baz() => Foo(ref field); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + [Fact] public async Task IgnorePostIncrement() { @@ -856,7 +882,7 @@ namespace ConsoleApplication1 public class MyClass { private MyStruct myStruct = default(MyStruct); - + private struct MyStruct { public int Value; From db0df32ad67c46091ed92d77d9d0cf5802193212 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 9 Aug 2016 01:23:50 -0300 Subject: [PATCH 057/234] Enable fields to be disposed when using member access expression Fixes #795 --- .../DisposableFieldNotDisposedAnalyzer.cs | 1 - .../Usage/DisposableFieldNotDisposedTests.cs | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs index e38d7959d..2e625e04d 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs @@ -96,7 +96,6 @@ private static bool CallsDisposeOnField(IFieldSymbol fieldSymbol, MethodDeclarat var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; if (memberAccess?.Name == null) return false; if (memberAccess.Name.Identifier.ToString() != "Dispose" || memberAccess.Name.Arity != 0) return false; - if (!memberAccess.Expression.IsKind(SyntaxKind.IdentifierName)) return false; return fieldSymbol.Equals(semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol); }); return hasDisposeCall; diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs index 123a05cb5..ba84e4bc6 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs @@ -210,6 +210,30 @@ public void Dispose() { } await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task WhenAFieldThatImplementsIDisposableIsDisposedWithThisDoesNotCreateDiagnostic() + { + const string source = @" + using System; + namespace ConsoleApplication1 + { + class TypeName : IDisposable + { + private D field = D.Create(); + public void Dispose() + { + this.field.Dispose(); + } + } + class D : IDisposable + { + public static D Create() => new D(); + public void Dispose() { } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task WhenAFieldThatImplementsIDisposableIsDisposedThroughImplicitImplementationDoesNotCreateDiagnostic() { From 719d83566aca05cc7bc650689b19a1e7685007e4 Mon Sep 17 00:00:00 2001 From: Vsevolod Krasnov Date: Thu, 11 Aug 2016 06:32:35 +0300 Subject: [PATCH 058/234] Fix 'GC.SuppressFinalize within the finally block' #776 (#819) --- ...ablesShouldCallSuppressFinalizeAnalyzer.cs | 2 +- ...posablesShouldCallSuppressFinalizeTests.cs | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs index 4ab5b1e3a..c19d84911 100644 --- a/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs @@ -56,7 +56,7 @@ private static void Analyze(SyntaxNodeAnalysisContext context) if (symbol.IsSealed && !ContainsUserDefinedFinalizer(symbol)) return; if (!ContainsNonPrivateConstructors(symbol)) return; - var statements = method.Body?.Statements.OfType(); + var statements = method.Body?.DescendantNodes().OfType(); if (statements != null) { foreach (var statement in statements) diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs index e90b46906..f145f40ab 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs @@ -58,6 +58,66 @@ public void Dispose() await VerifyCSharpDiagnosticAsync(test, expected); } + [Fact] + public async void DoNotWarnIfClassImplementsIDisposableWithSuppressFinalizeCallInFinally() + { + const string test = @" + public class MyType : System.IDisposable + { + public void Dispose() + { + try + { + } + finally + { + System.GC.SuppressFinalize(this); + } + } + }"; + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] + public async void DoNotWarnIfClassImplementsIDisposableWithSuppressFinalizeCallInIf() + { + const string test = @" + public class MyType : System.IDisposable + { + public void Dispose() + { + if (true) + { + System.GC.SuppressFinalize(this); + } + } + }"; + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] + public async void DoNotWarnIfClassImplementsIDisposableWithSuppressFinalizeCallInElse() + { + const string test = @" + public class MyType : System.IDisposable + { + public void Dispose() + { + if (true) + { + } + else + { + System.GC.SuppressFinalize(this); + } + } + }"; + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + [Fact] public async Task NoWarningIfClassImplementsDisposableCallsSuppressFinalizeAndCallsDisposeWithThis() { From 7cfff1c99f54fe3000cc93bcb000ad54678fa548 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 9 Aug 2016 00:44:56 -0300 Subject: [PATCH 059/234] Enable CC0029 analyzer to work with arrow methods Fixes #809 --- ...ablesShouldCallSuppressFinalizeAnalyzer.cs | 29 +++++++++---------- ...posablesShouldCallSuppressFinalizeTests.cs | 10 +++++++ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs index c19d84911..b70f8d735 100644 --- a/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.cs @@ -38,6 +38,7 @@ private static void Analyze(SyntaxNodeAnalysisContext context) var semanticModel = context.SemanticModel; var method = (MethodDeclarationSyntax)context.Node; + if (method.Body == null && method.ExpressionBody == null) return; var methodSymbol = semanticModel.GetDeclaredSymbol(method); var isImplicitDispose = methodSymbol.ToString().Contains($"{methodSymbol.ContainingType.Name}.Dispose("); @@ -56,24 +57,22 @@ private static void Analyze(SyntaxNodeAnalysisContext context) if (symbol.IsSealed && !ContainsUserDefinedFinalizer(symbol)) return; if (!ContainsNonPrivateConstructors(symbol)) return; - var statements = method.Body?.DescendantNodes().OfType(); - if (statements != null) + var expressions = method.Body != null + ? method.Body?.DescendantNodes().OfType().Select(e => e.Expression) + : new[] { method.ExpressionBody.Expression }; + foreach (var expression in expressions) { - foreach (var statement in statements) - { - var invocation = statement.Expression as InvocationExpressionSyntax; - var suppress = invocation?.Expression as MemberAccessExpressionSyntax; + var suppress = (expression as InvocationExpressionSyntax)?.Expression as MemberAccessExpressionSyntax; - if (suppress?.Name.ToString() != "SuppressFinalize") - continue; + if (suppress?.Name.ToString() != "SuppressFinalize") + continue; - var containingType = semanticModel.GetSymbolInfo(suppress.Expression).Symbol as INamedTypeSymbol; - if (containingType?.ContainingNamespace.Name != "System") - continue; + var containingType = semanticModel.GetSymbolInfo(suppress.Expression).Symbol as INamedTypeSymbol; + if (containingType?.ContainingNamespace.Name != "System") + continue; - if (containingType.Name == "GC") - return; - } + if (containingType.Name == "GC") + return; } context.ReportDiagnostic(Diagnostic.Create(Rule, methodSymbol.Locations[0], symbol.Name)); } @@ -104,4 +103,4 @@ private static bool IsNestedPrivateType(ISymbol symbol) return IsNestedPrivateType(symbol.ContainingType); } } -} \ No newline at end of file +} diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs index f145f40ab..487f2b557 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs @@ -7,6 +7,16 @@ namespace CodeCracker.Test.CSharp.Usage { public class DisposablesShouldCallSuppressFinalizeTests : CodeFixVerifier { + [Fact] + public async void AlreadyCallsSuppressFinalizeWithArrowMethod() + { + const string source = @" + public class MyType : System.IDisposable + { + public void Dispose() => System.GC.SuppressFinalize(this); + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } [Fact] public async void AlreadyCallsSuppressFinalize() From b40843eab577001bcb2ce146df5ff5a6c0abc62e Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 19 Aug 2016 12:09:58 -0300 Subject: [PATCH 060/234] Ignore member order on ReadonlyFieldAnalyzer Fix #812 Add constructor to the top of the list so we add fields with constructors initializers first --- .../Usage/ReadonlyFieldAnalyzer.cs | 14 +++++++++++ .../Usage/ReadonlyFieldTests.cs | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index 401e7ef48..d9db192ba 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -36,6 +36,19 @@ private static void AnalyzeCompilation(CompilationStartAnalysisContext compilati compilationStartAnalysisContext.RegisterSyntaxTreeAction(context => AnalyzeTree(context, compilation)); } + private struct MethodKindComparer : IComparer + { + public int Compare(MethodKind x, MethodKind y) => + x - y == 0 + ? 0 + : (x == MethodKind.Constructor + ? 1 + : (y == MethodKind.Constructor + ? -1 + : x - y)); + } + private static readonly MethodKindComparer methodKindComparer = new MethodKindComparer(); + private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation compilation) { if (context.IsGenerated()) return; @@ -51,6 +64,7 @@ private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation c var typeSymbol = semanticModel.GetDeclaredSymbol(type); if (typeSymbol == null) continue; var methods = typeSymbol.GetAllMethodsIncludingFromInnerTypes(); + methods = methods.OrderByDescending(m => m.MethodKind, methodKindComparer).ToList(); foreach (var method in methods) { foreach (var syntaxReference in method.DeclaringSyntaxReferences) diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index efbaa8c12..e4181d876 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -967,5 +967,29 @@ public Person(string name) }; await VerifyCSharpDiagnosticAsync(source, expected); } + + [Fact] + public async Task IgnoreWhenConstructorIsTheLastMember() + { + const string source = @" +class Test +{ + private int value; + public int Value + { + get { return value; } + set { this.value = value; } + } + public void Foo() + { + value = 1; + } + public Test() + { + value = 8; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } From 822f0bfaac570ac60992f7f8288a8c73d5252bf7 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 20 Aug 2016 14:46:54 -0300 Subject: [PATCH 061/234] Ignore methods that implement interface in TaskNameAsync (CC0061) Fix #793 Also, refactor the search for interface members on TaskNameAsyncAnalyzer and MakeMethodStaticAnalyzer. --- .../Design/MakeMethodStaticAnalyzer.cs | 12 +---- .../Extensions/CSharpAnalyzerExtensions.cs | 33 ++++++++++++ .../Style/TaskNameAsyncAnalyzer.cs | 15 +++--- .../Style/TaskNameASyncTests.cs | 54 +++++++++++++++++++ 4 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs b/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs index b5c5a60b4..a5fecd666 100644 --- a/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/MakeMethodStaticAnalyzer.cs @@ -52,16 +52,8 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) var semanticModel = context.SemanticModel; var methodSymbol = semanticModel.GetDeclaredSymbol(method); - var theClass = methodSymbol.ContainingType; - if (theClass.TypeKind == TypeKind.Interface) return; - - var interfaceMembersWithSameName = theClass.AllInterfaces.SelectMany(i => i.GetMembers(methodSymbol.Name)); - foreach (var memberSymbol in interfaceMembersWithSameName) - { - if (memberSymbol.Kind != SymbolKind.Method) continue; - var implementation = theClass.FindImplementationForInterfaceMember(memberSymbol); - if (implementation != null && implementation.Equals(methodSymbol)) return; - } + if (methodSymbol == null) return; + if (methodSymbol.IsImplementingInterface()) return; if (method.Body == null) { diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 358b3fc6c..50065c3d7 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -877,5 +877,38 @@ public static string FindAvailableIdentifierName(this SemanticModel semanticMode name = baseName + inscrementer++; return name; } + + public static bool IsImplementingInterface(this MemberDeclarationSyntax member, SemanticModel semanticModel) => + semanticModel.GetDeclaredSymbol(member).IsImplementingInterface(); + + public static bool IsImplementingInterface(this ISymbol memberSymbol) + { + if (memberSymbol == null) return false; + IMethodSymbol methodSymbol; + IEventSymbol eventSymbol; + IPropertySymbol propertySymbol; + if ((methodSymbol = memberSymbol as IMethodSymbol) != null) + { + if (methodSymbol.ExplicitInterfaceImplementations.Any()) return true; + } + else if ((propertySymbol = memberSymbol as IPropertySymbol) != null) + { + if (propertySymbol.ExplicitInterfaceImplementations.Any()) return true; + } + else if ((eventSymbol = memberSymbol as IEventSymbol) != null) + { + if (eventSymbol.ExplicitInterfaceImplementations.Any()) return true; + } + else return false; + var type = memberSymbol.ContainingType; + if (type == null) return false; + var interfaceMembersWithSameName = type.AllInterfaces.SelectMany(i => i.GetMembers(memberSymbol.Name)); + foreach (var interfaceMember in interfaceMembersWithSameName) + { + var implementation = type.FindImplementationForInterfaceMember(interfaceMember); + if (implementation != null && implementation.Equals(memberSymbol)) return true; + } + return false; + } } } \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs index 5fd40d27c..d90d22915 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs @@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using System.Collections.Immutable; +using System.Linq; namespace CodeCracker.CSharp.Style { @@ -43,15 +44,15 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(diag); return; } - var returnType = context.SemanticModel.GetSymbolInfo(method.ReturnType).Symbol as INamedTypeSymbol; + var semanticModel = context.SemanticModel; + var returnType = semanticModel.GetSymbolInfo(method.ReturnType).Symbol as INamedTypeSymbol; if (returnType == null) return; - if (returnType.ToString() == "System.Threading.Tasks.Task" || - (returnType.IsGenericType && returnType.ConstructedFrom.ToString() == "System.Threading.Tasks.Task")) - { - context.ReportDiagnostic(diag); - } - + if (returnType.ToString() != "System.Threading.Tasks.Task" && + (!returnType.IsGenericType || returnType.ConstructedFrom.ToString() != "System.Threading.Tasks.Task")) + return; + if (method.IsImplementingInterface(semanticModel)) return; + context.ReportDiagnostic(diag); } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs index 919a54fe6..76107647d 100644 --- a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs @@ -178,5 +178,59 @@ public Task TestAsync() }"; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task IgnoreMethodFromImplicitlyImplementedInterface() + { + const string source = @" +using System.Threading.Tasks; +public interface IBar +{ + Task Foo(); +} +public class Bar : IBar +{ + public Task Foo() + { + throw new System.NotImplementedException(); + } +}"; + //we still get the diagnostic for the interface itself + var expected = new DiagnosticResult + { + Id = DiagnosticId.TaskNameAsync.ToDiagnosticId(), + Message = string.Format(TaskNameAsyncAnalyzer.MessageFormat, "FooAsync"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 10) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task IgnoreMethodFromExplicitlyImplementedInterface() + { + const string source = @" +using System.Threading.Tasks; +public interface IBar +{ + Task Foo(); +} +public class Bar : IBar +{ + Task IBar.Foo() + { + throw new System.NotImplementedException(); + } +}"; + //we still get the diagnostic for the interface itself + var expected = new DiagnosticResult + { + Id = DiagnosticId.TaskNameAsync.ToDiagnosticId(), + Message = string.Format(TaskNameAsyncAnalyzer.MessageFormat, "FooAsync"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 10) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } } } \ No newline at end of file From 17b6b0233a9bc48b774579b756159f3676a7061f Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 20 Aug 2016 19:48:28 -0300 Subject: [PATCH 062/234] Update StringBuilderInLoopAnalyzer to ignore some member accesses If the member access is to a variable declared within the loop, we should not be raising a diagnostic. Fix #797 --- .../StringBuilderInLoopAnalyzer.cs | 16 ++++++++++--- .../Performance/StringBuilderInLoopTests.cs | 24 ++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs b/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs index 1ef255876..27427a1f3 100644 --- a/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs @@ -36,11 +36,11 @@ private static void AnalyzeAssignment(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; var assignmentExpression = (AssignmentExpressionSyntax)context.Node; - var whileStatement = assignmentExpression.FirstAncestorOfType(typeof(WhileStatementSyntax), + var loopStatement = assignmentExpression.FirstAncestorOfType(typeof(WhileStatementSyntax), typeof(ForStatementSyntax), typeof(ForEachStatementSyntax), typeof(DoStatementSyntax)); - if (whileStatement == null) return; + if (loopStatement == null) return; var semanticModel = context.SemanticModel; var arrayAccess = assignmentExpression.Left as ElementAccessExpressionSyntax; var symbolForAssignment = arrayAccess != null @@ -58,7 +58,17 @@ private static void AnalyzeAssignment(SyntaxNodeAnalysisContext context) } else if (type.Name != "String") return; // Do not analyze a string declared within the loop. - if (symbolForAssignment is ILocalSymbol && whileStatement.DescendantTokens(((ILocalSymbol)symbolForAssignment).DeclaringSyntaxReferences[0].Span).Any()) return; + if (symbolForAssignment is ILocalSymbol && loopStatement.DescendantTokens(((ILocalSymbol)symbolForAssignment).DeclaringSyntaxReferences[0].Span).Any()) return; + var memberAccess = assignmentExpression.Left as MemberAccessExpressionSyntax; + if (memberAccess != null) + { + var memberAccessExpressionSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol as ILocalSymbol; + if (memberAccessExpressionSymbol != null) + { + if (loopStatement.DescendantTokens(memberAccessExpressionSymbol.DeclaringSyntaxReferences[0].Span).Any()) + return; + } + } if (assignmentExpression.IsKind(SyntaxKind.SimpleAssignmentExpression)) { if (!(assignmentExpression.Right?.IsKind(SyntaxKind.AddExpression) ?? false)) return; diff --git a/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs b/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs index c31e7ebac..9f14bdcb5 100644 --- a/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs @@ -29,7 +29,6 @@ public void Method() { } await VerifyCSharpHasNoDiagnosticsAsync(source); } - [Fact] public async Task WhileWithoutStringConcatDoesNotCreateDiagnostic() { @@ -631,5 +630,28 @@ public void Looper(ref int a) }".WrapInCSharpClass(); await VerifyCSharpHasNoDiagnosticsAsync(source); } + + [Fact] + public async Task IgnoreWhenVariableInTheLoopContextIsChanged() + { + const string source = @" +class MyObject +{ + public string MyObjectString; +} +class MyClass +{ + private readonly System.Collections.Generic.List items = new System.Collections.Generic.List(); + private void M(string suffix) + { + foreach (MyObject o in items) + { + o.MyObjectString += suffix; + } + } +} + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From 27fd04d11cecb86843626b470da26ca3713841dc Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Mon, 22 Aug 2016 08:08:03 -0300 Subject: [PATCH 063/234] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f3ae91e29..f928ce0d9 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ msbuild Then add a reference to CodeCracker.dll from within the Analyzers node inside References, in Visual Studio. +## SonarQube Plugin + +CodeCracker has a SonarQube Plugin that was downloaded at ([Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). + ## Contributing Questions, comments, bug reports, and pull requests are all welcome. From 194ba06aae5859f9aaf8e69fdb81eba6474458d5 Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Mon, 22 Aug 2016 08:08:39 -0300 Subject: [PATCH 064/234] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f928ce0d9..1036a22c1 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Then add a reference to CodeCracker.dll from within the Analyzers node inside Re ## SonarQube Plugin -CodeCracker has a SonarQube Plugin that was downloaded at ([Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). +CodeCracker has a SonarQube Plugin that can downloaded at [Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). ## Contributing From 442eb755a150d4d1fbd1006d47ae2b5bdef62990 Mon Sep 17 00:00:00 2001 From: Lazaro Fernandes Lima Suleiman Date: Sun, 28 Aug 2016 16:51:48 -0300 Subject: [PATCH 065/234] Add support to remove unnecessary '.ToString()' in a string concatenation --- src/CSharp/CodeCracker/CodeCracker.csproj | 2 + ...ryToStringInStringConcatenationAnalyzer.cs | 74 +++++++ ...ingInStringConcatenationCodeFixProvider.cs | 54 +++++ src/Common/CodeCracker.Common/DiagnosticId.cs | 1 + .../CodeCracker.Test/CodeCracker.Test.csproj | 1 + ...ssaryToStringInStringConcatenationTests.cs | 208 ++++++++++++++++++ 6 files changed, 340 insertions(+) create mode 100644 src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs create mode 100644 src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationCodeFixProvider.cs create mode 100644 test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index e1a60a05e..965fba6b7 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -83,6 +83,8 @@ + + diff --git a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs new file mode 100644 index 000000000..fb9a0974a --- /dev/null +++ b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs @@ -0,0 +1,74 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Text; +using System.Collections.Immutable; +using System.Linq; + +namespace CodeCracker.CSharp.Style +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class UnnecessaryToStringInStringConcatenationAnalyzer : DiagnosticAnalyzer + { + internal const string Title = "Unnecessary '.ToString()' call in string concatenation."; + internal const string MessageFormat = Title; + internal const string Category = SupportedCategories.Style; + const string Description = "The runtime automatically calls '.ToString()' method for" + + " string concatenation operations when there is no parameters. Remove them."; + + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId.UnnecessaryToStringInStringConcatenation.ToDiagnosticId(), + Title, + MessageFormat, + Category, + DiagnosticSeverity.Info, + customTags: WellKnownDiagnosticTags.Unnecessary, + isEnabledByDefault: true, + description: Description, + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.UnnecessaryToStringInStringConcatenation)); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) => + context.RegisterSyntaxNodeAction(Analyzer, SyntaxKind.AddExpression); + + private static void Analyzer(SyntaxNodeAnalysisContext context) + { + if (context.IsGenerated()) return; + var addExpression = context.Node as BinaryExpressionSyntax; + + if (!addExpression.IsKind(SyntaxKind.AddExpression)) return; + + var hasPlusToken = addExpression.ChildNodesAndTokens().Any(x => x.IsKind(SyntaxKind.PlusToken)); + var hasInvocationExpression = addExpression.ChildNodesAndTokens().Any(x => x.IsKind(SyntaxKind.InvocationExpression)); + + //string concatenation must have PlusToken and an InvocationExpression + if (!hasPlusToken || !hasInvocationExpression) return; + var invocationExpressionsThatHaveToStringCall = GetInvocationExpressionsThatHaveToStringCall(addExpression); + + foreach (var expression in invocationExpressionsThatHaveToStringCall) + { + var lastDot = expression.Expression.ChildNodesAndTokens().Last(x => x.IsKind(SyntaxKind.DotToken)); + var argumentList = expression.ChildNodes().Last(x => x.IsKind(SyntaxKind.ArgumentList)); + + //Only default call to ToString method must be accepted + if (expression.ArgumentList.Arguments.Count > 0) + break; + + var tree = expression.SyntaxTree; + var textspan = new TextSpan(lastDot.Span.Start, argumentList.Span.End - lastDot.Span.Start); + + var diagnostic = Diagnostic.Create(Rule, Location.Create(context.Node.SyntaxTree, textspan)); + context.ReportDiagnostic(diagnostic); + } + } + + private static System.Collections.Generic.List GetInvocationExpressionsThatHaveToStringCall(BinaryExpressionSyntax addExpression) + { + return addExpression.ChildNodes().OfType() + .Where(x => x.Expression.ToString().EndsWith(@".ToString")) + .ToList(); + } + } +} \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationCodeFixProvider.cs new file mode 100644 index 000000000..4d895d8f5 --- /dev/null +++ b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationCodeFixProvider.cs @@ -0,0 +1,54 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeCracker.CSharp.Style +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UnnecessaryParenthesisCodeFixProvider)), Shared] + public class UnnecessaryToStringInStringConcatenationCodeFixProvider : CodeFixProvider + { + public sealed override ImmutableArray FixableDiagnosticIds => + ImmutableArray.Create(DiagnosticId.UnnecessaryToStringInStringConcatenation.ToDiagnosticId()); + + public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var diagnostic = context.Diagnostics.First(); + context.RegisterCodeFix(CodeAction.Create("Remove unnecessary ToString", ct => RemoveUnnecessaryToStringAsync(context.Document, diagnostic, ct), nameof(UnnecessaryToStringInStringConcatenationCodeFixProvider)), diagnostic); + return Task.FromResult(0); + } + private static async Task RemoveUnnecessaryToStringAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + + var invocationExpression = + root + .FindToken(diagnostic.Location.SourceSpan.Start) + .Parent + .AncestorsAndSelf() + .OfType() + .First(); + + var onlyMemberAccessNode = + invocationExpression + .ChildNodes() + .First() + .ChildNodes() + .First(); + + var newRoot = root.ReplaceNode(invocationExpression, onlyMemberAccessNode); + + var newDocument = document.WithSyntaxRoot(newRoot); + return newDocument; + } + + } + +} \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index 156dc6285..7d48257fd 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -80,5 +80,6 @@ public enum DiagnosticId NameOf_External = 108, StringFormatArgs_ExtraArgs = 111, AlwaysUseVarOnPrimitives = 105, + UnnecessaryToStringInStringConcatenation = 118, } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index b17ba4a79..7168f11df 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -146,6 +146,7 @@ + diff --git a/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs b/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs new file mode 100644 index 000000000..077f095e7 --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs @@ -0,0 +1,208 @@ +using CodeCracker.CSharp.Style; +using Microsoft.CodeAnalysis; +using System.Threading.Tasks; +using Xunit; + +namespace CodeCracker.Test.CSharp.Style +{ + public class UnnecessaryToStringInStringConcatenationTests : CodeFixVerifier + { + [Fact] + public async Task InstantiatingAnObjectAndCallToStringInsideAStringConcatenationShouldGenerateDiagnosticResult() + { + const string source = @"var foo = ""a"" + new object().ToString();"; + + var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(1, 29); + + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task InstantiatingAnStringBuilderAndCallToStringInsideAStringConcatenationShouldGenerateDiagnosticResult() + { + const string source = @"var foo = ""a"" + new System.Text.StringBuilder().ToString();"; + + var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(1, 48); + + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task CallToStringForAnInstantiatedObjectInsideAStringConcatenationShouldGenerateDiagnosticResult() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + class AuxClass + { + public override void ToString() + { + return ""Test""; + } + } + + class TypeName + { + public void Foo() + { + var auxClass = new AuxClass(); + + var bar = ""a"" + new AuxClass().ToString(); + var foo = ""a"" + auxClass.ToString(); + var far = ""a"" + new AuxClass().ToString() + auxClass.ToString() + new object().ToString(""C""); + } + } + }"; + + var expected1 = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(20, 47); + var expected2 = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(21, 41); + var expected3 = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(22, 47); + var expected4 = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(22, 69); + + var expected = new DiagnosticResult[] { expected1, expected2, expected3, expected4 }; + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async Task CallToStringInsideAStringConcatenationWithAFormatParameterShouldNotGenerateDiagnosticResult() + { + const string source = @"var salary = ""salary: "" + 1000.ToString(""C"");"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + + [Fact] + public async Task CallToStringOutsideAStringConcatenationWithoutParameterShouldNotGenerateDiagnosticResult() + { + const string source = @"var value = 1000.ToString();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + + private static DiagnosticResult CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(int expectedRow, int expectedColumn) + { + var expected = new DiagnosticResult + { + Id = DiagnosticId.UnnecessaryToStringInStringConcatenation.ToDiagnosticId(), + Message = "Unnecessary '.ToString()' call in string concatenation.", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", expectedRow, expectedColumn) } + }; + + return expected; + } + + [Fact] + public async Task FixReplacesToStringCallInAStringConcatenationWithAVariable() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + class TypeName + { + public async Task Foo() + { + var text = ""def""; + var a = ""abc"" + text.ToString(); + Console.Log(a); + } + } + }"; + + const string expected = @" + using System; + + namespace ConsoleApplication1 + { + class TypeName + { + public async Task Foo() + { + var text = ""def""; + var a = ""abc"" + text; + Console.Log(a); + } + } + }"; + await VerifyCSharpFixAsync(test, expected); + } + + + [Fact] + public async Task FixReplacesToStringCallInAStringConcatenation() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + class TypeName + { + public async Task Foo() + { + var a = ""abc"" + ""def"".ToString(); + Console.Log(a); + } + } + }"; + + const string expected = @" + using System; + + namespace ConsoleApplication1 + { + class TypeName + { + public async Task Foo() + { + var a = ""abc"" + ""def""; + Console.Log(a); + } + } + }"; + await VerifyCSharpFixAsync(test, expected); + } + + [Fact] + public async Task FixReplacesToStringCallInAStringConcatenationWithAnObject() + { + const string test = @" + using System; + + namespace ConsoleApplication1 + { + class TypeName + { + public async Task Foo() + { + var foo = ""a"" + new object().ToString(); + Console.Log(foo); + } + } + }"; + + const string expected = @" + using System; + + namespace ConsoleApplication1 + { + class TypeName + { + public async Task Foo() + { + var foo = ""a"" + new object(); + Console.Log(foo); + } + } + }"; + await VerifyCSharpFixAsync(test, expected); + } + } +} \ No newline at end of file From 21dc1da2bce6a7b1690033fd41c36381266fbad4 Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Thu, 25 Aug 2016 17:21:32 -0300 Subject: [PATCH 066/234] Fix #829 --- src/CSharp/CodeCracker/CodeCracker.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index f659d5f96..e08549efe 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -19,6 +19,7 @@ This is a community project, free and open source. Everyone is invited to contri + true From 74853e60ea10e8ee29ac69cc988c0dd1a5016f27 Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Fri, 26 Aug 2016 20:38:49 -0300 Subject: [PATCH 067/234] Fix UseStaticRegexIsMatchAnalyzer when facing a member access expr Fixes #822 --- .../UseStaticRegexIsMatchAnalyzer.cs | 2 +- .../Performance/UseStaticRegexIsMatchTests.cs | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Performance/UseStaticRegexIsMatchAnalyzer.cs b/src/CSharp/CodeCracker/Performance/UseStaticRegexIsMatchAnalyzer.cs index 2ecfa57dc..19c4e2374 100644 --- a/src/CSharp/CodeCracker/Performance/UseStaticRegexIsMatchAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/UseStaticRegexIsMatchAnalyzer.cs @@ -40,7 +40,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) var methodSymbol = context.SemanticModel.GetSymbolInfo(memberExpression).Symbol; if (methodSymbol?.ContainingType.ToString() != "System.Text.RegularExpressions.Regex" || methodSymbol.IsStatic) return; - + if (!(memberExpression.Expression is IdentifierNameSyntax)) return; var variableSymbol = context.SemanticModel.GetSymbolInfo(((IdentifierNameSyntax)memberExpression.Expression).Identifier.Parent).Symbol; if (variableSymbol?.Kind != SymbolKind.Local) return; diff --git a/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs b/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs index 969563a93..c16424c06 100644 --- a/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs @@ -119,5 +119,56 @@ public async Task Foo() }"; await VerifyCSharpFixAsync(test, fixtest, 1, allowNewCompilerDiagnostics: true); //todo: should not need to allow new compiler diagnostic, fix test infrastructure to understand the Regex type } + + [Fact] + public async Task IgnoresIsMatchCallClassMember() + { + const string testStatic = @" + public class RegexTestClass + { + private TestModel testModel; + + private void Test(string text) + { + if (testModel.Regex.IsMatch(text)) + { + return; + } + } + } + + public class TestModel + { + public Regex Regex { get; set; } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(testStatic); + } + + [Fact] + public async Task IgnoresIsMatchCallClassMemberInsideClass() + { + const string testStatic = @" + public class RegexTestClass + { + private C c; + + private void Test(string text) + { + if (c.TestModel.Regex.IsMatch(text)) + { + return; + } + } + } + public class C + { + public TestModel TestModel { get; set; } + } + public class TestModel + { + public System.Text.RegularExpressions.Regex Regex { get; set; } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(testStatic); + } } } \ No newline at end of file From 160d12b834d7522a24807a727b402ba79031f475 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 26 Aug 2016 01:31:50 -0300 Subject: [PATCH 068/234] Ignore when iteration variable altered in ForInArrayAnalyzer Issued touched assignment, but also checked for pre and post fix unary, ref and out. Closes #814 --- .../CodeCracker/Style/ForInArrayAnalyzer.cs | 58 +++++++++++++---- .../CodeCracker.Test/Style/ForInArrayTests.cs | 65 +++++++++++++++++++ 2 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs b/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs index 1a95477bf..d76eee1d0 100644 --- a/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/ForInArrayAnalyzer.cs @@ -4,6 +4,8 @@ using Microsoft.CodeAnalysis.Diagnostics; using System.Collections.Immutable; using System.Linq; +using System; +using System.Collections.Generic; namespace CodeCracker.CSharp.Style { @@ -65,24 +67,52 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) return !identifierSymbol.Equals(arrayId); }); if (otherUsesOfIndexToken != 0) return; - var arrayAccessorSymbols = (from s in forBlock.Statements.OfType() - where s.Declaration.Variables.Count == 1 - let declaration = s.Declaration.Variables.First() - where declaration?.Initializer?.Value is ElementAccessExpressionSyntax - let iterableSymbol = semanticModel.GetDeclaredSymbol(declaration) - let iterableType = ((ILocalSymbol)iterableSymbol).Type - where !(iterableType.IsPrimitive() ^ iterableType.IsValueType) - let init = (ElementAccessExpressionSyntax)declaration.Initializer.Value - let initSymbol = semanticModel.GetSymbolInfo(init.ArgumentList.Arguments.First().Expression).Symbol - where controlVarId.Equals(initSymbol) - let someArrayInit = semanticModel.GetSymbolInfo(init.Expression).Symbol - where arrayId.Equals(someArrayInit) - select arrayId).ToList(); - if (!arrayAccessorSymbols.Any()) return; + var iterableSymbols = (from s in forBlock.Statements.OfType() + where s.Declaration.Variables.Count == 1 + let declaration = s.Declaration.Variables.First() + where declaration?.Initializer?.Value is ElementAccessExpressionSyntax + let iterableSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declaration) + let iterableType = iterableSymbol.Type + where !(iterableType.IsPrimitive() ^ iterableType.IsValueType) + let init = (ElementAccessExpressionSyntax)declaration.Initializer.Value + let initSymbol = semanticModel.GetSymbolInfo(init.ArgumentList.Arguments.First().Expression).Symbol + where controlVarId.Equals(initSymbol) + let someArrayInit = semanticModel.GetSymbolInfo(init.Expression).Symbol + where arrayId.Equals(someArrayInit) + select iterableSymbol).ToList(); + if (!iterableSymbols.Any()) return; + if (IsIterationVariableWritten(semanticModel, forBlock, iterableSymbols)) return; var diagnostic = Diagnostic.Create(Rule, forStatement.ForKeyword.GetLocation()); context.ReportDiagnostic(diagnostic); } + private static bool IsIterationVariableWritten(SemanticModel semanticModel, BlockSyntax forBlock, List iterableSymbols) + { + var forDescendants = forBlock.DescendantNodes(); + var assignments = (from assignmentExpression in forDescendants.OfType() + let assignmentLeftSymbol = semanticModel.GetSymbolInfo(assignmentExpression.Left).Symbol + where iterableSymbols.Any(i => i.Equals(assignmentLeftSymbol)) + select assignmentExpression).ToList(); + if (assignments.Any()) return true; + var refs = (from argument in forDescendants.OfType() + where argument.RefOrOutKeyword != null + let argumentExpressionSymbol = semanticModel.GetSymbolInfo(argument.Expression).Symbol + where iterableSymbols.Any(i => i.Equals(argumentExpressionSymbol)) + select argument).ToList(); + if (refs.Any()) return true; + var postfixUnaries = (from postfixUnaryExpression in forDescendants.OfType() + let operandSymbol = semanticModel.GetSymbolInfo(postfixUnaryExpression.Operand).Symbol + where iterableSymbols.Any(i => i.Equals(operandSymbol)) + select postfixUnaryExpression).ToList(); + if (postfixUnaries.Any()) return true; + var prefixUnaries = (from postfixUnaryExpression in forDescendants.OfType() + let operandSymbol = semanticModel.GetSymbolInfo(postfixUnaryExpression.Operand).Symbol + where iterableSymbols.Any(i => i.Equals(operandSymbol)) + select postfixUnaryExpression).ToList(); + if (prefixUnaries.Any()) return true; + return false; + } + private static bool IsEnumerable(ISymbol arrayId) { var type = (arrayId as ILocalSymbol)?.Type diff --git a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs index 780687f64..65b0345b9 100644 --- a/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ForInArrayTests.cs @@ -849,5 +849,70 @@ static void Goo() }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } + + [Fact] + public async Task IgnoreWhenWouldChangeTheIterationVariableWithAssignment() + { + var source = @" +var a = new[] { 1 }; +for (var i = 0; i < a.Length; i++) +{ + var item = a[i]; + item = 0; +}".WrapInCSharpMethod(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task IgnoreWhenWouldChangeTheIterationVariableWithRef() + { + var source = @" +void Foo() +{ + var a = new[] { 1 }; + for (var i = 0; i < a.Length; i++) + { + var item = a[i]; + Bar(ref item); + } +} +void Bar(ref int i) +{ + i = 1; +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task IgnoreWhenWouldChangeTheIterationVariableWithPostfixUnary() + { + var source = @" +void Foo() +{ + var a = new[] { 1 }; + for (var i = 0; i < a.Length; i++) + { + var item = a[i]; + item++; + } +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task IgnoreWhenWouldChangeTheIterationVariableWithPrefixUnary() + { + var source = @" +void Foo() +{ + var a = new[] { 1 }; + for (var i = 0; i < a.Length; i++) + { + var item = a[i]; + ++item; + } +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From 4dc4707dc1d7556dbeb8684b44f7e656223cff5a Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Mon, 5 Sep 2016 13:56:11 -0300 Subject: [PATCH 069/234] Fix #774 - ignore pointer declaration --- .../MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs | 3 +++ .../MakeLocalVariablesConstWhenItIsPossibleTests.cs | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs index f5c8e2b29..869a15ed4 100644 --- a/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs @@ -36,6 +36,8 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var localDeclaration = (LocalDeclarationStatementSyntax)context.Node; var semanticModel = context.SemanticModel; + if (localDeclaration.GetType().IsPointer) return; + if (!localDeclaration.IsConst && IsDeclarationConstFriendly(localDeclaration, semanticModel) && AreVariablesOnlyWrittenInsideDeclaration(localDeclaration, semanticModel) ) @@ -61,6 +63,7 @@ static bool IsDeclarationConstFriendly(LocalDeclarationStatementSyntax declarati // if reference type, value is null? var variableTypeName = declaration.Declaration.Type; var variableType = semanticModel.GetTypeInfo(variableTypeName).ConvertedType; + if (variableType.TypeKind == TypeKind.Pointer) return false; if (variableType.IsReferenceType && variableType.SpecialType != SpecialType.System_String && constantValue.Value != null) return false; // nullable? diff --git a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs index 1fc75b5c0..8cfa21591 100644 --- a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs @@ -52,6 +52,13 @@ public async Task IgnoresVariablesThatChangesValueOutsideDeclaration() await VerifyCSharpHasNoDiagnosticsAsync(test); } + public async Task IgnoresPointerDeclarations() + { + var test = @"void* value = null;".WrapInCSharpMethod(); + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + [Fact] public async Task CreateDiagnosticsWhenAssigningAPotentialConstant() { From 352b6b33a365466573d43d3247fda1aa360fa0ef Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 6 Sep 2016 11:41:45 -0300 Subject: [PATCH 070/234] Remove unnecessary check on MakeLocalVariableConstWhenItIsPossibleAnalyzer Also add `Fact` to missing test Related to #774 --- .../MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs | 2 -- .../Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs index 869a15ed4..60dc5f397 100644 --- a/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs @@ -36,8 +36,6 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var localDeclaration = (LocalDeclarationStatementSyntax)context.Node; var semanticModel = context.SemanticModel; - if (localDeclaration.GetType().IsPointer) return; - if (!localDeclaration.IsConst && IsDeclarationConstFriendly(localDeclaration, semanticModel) && AreVariablesOnlyWrittenInsideDeclaration(localDeclaration, semanticModel) ) diff --git a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs index 8cfa21591..3bbd8e378 100644 --- a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs @@ -52,6 +52,7 @@ public async Task IgnoresVariablesThatChangesValueOutsideDeclaration() await VerifyCSharpHasNoDiagnosticsAsync(test); } + [Fact] public async Task IgnoresPointerDeclarations() { var test = @"void* value = null;".WrapInCSharpMethod(); From 6f3d5aabb4ba37314732e290d88fb8a4baefe275 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 6 Sep 2016 12:40:43 -0300 Subject: [PATCH 071/234] Add v1.0.1 changelog --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7753429db..31c87d874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Change Log +## [v1.0.1](https://github.com/code-cracker/code-cracker/tree/v1.0.1) (2016-09-06) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0...v1.0.1) + +**Implemented enhancements:** + +- Auto generated files detection [\#773](https://github.com/code-cracker/code-cracker/issues/773) + +**Fixed bugs:** + +- Bug: "UseStaticRegexIsMatchAnalyzer" causes an exception \(CC0081\) [\#822](https://github.com/code-cracker/code-cracker/issues/822) +- CC0006 could break code when changing to foreach [\#814](https://github.com/code-cracker/code-cracker/issues/814) +- BUG: Make readonly \(CC0052\) is incorrectly raised if constructor shows up after member that uses the field [\#812](https://github.com/code-cracker/code-cracker/issues/812) +- Bug: ArgumentNullException on CallExtensionMethodAsExtensionAnalyzer \(CC0026\) [\#810](https://github.com/code-cracker/code-cracker/issues/810) +- BUG: GC.SuppressFinalize with arrow methods \(CC0029\) [\#809](https://github.com/code-cracker/code-cracker/issues/809) +- Bug: CC0039 False positive when concatenating to loop variable propery/field \(StringBuilderInLoop\) [\#797](https://github.com/code-cracker/code-cracker/issues/797) +- Bug: CC0033 appears again after adding 'this' keyword [\#795](https://github.com/code-cracker/code-cracker/issues/795) +- CC0061: Implementing interface using async [\#793](https://github.com/code-cracker/code-cracker/issues/793) +- CC0052 Make field readonly does not take ref out into consideration. [\#788](https://github.com/code-cracker/code-cracker/issues/788) +- BUG: CallExtensionMethodAsExtensionAnalyzer threw exception when project language was C\# 5.0 [\#781](https://github.com/code-cracker/code-cracker/issues/781) +- Bug: UseInvokeMethodToFireEventAnalyzer \(CC0031\) should not raise a diagnostic when already checked for null with a ternary [\#779](https://github.com/code-cracker/code-cracker/issues/779) +- BUG: GC.SuppressFinalize within any block \(CC0029\) [\#776](https://github.com/code-cracker/code-cracker/issues/776) +- BUG: CC0052 \(Make readonly\) should not be applied to complex value types [\#775](https://github.com/code-cracker/code-cracker/issues/775) +- BUG: CC0030 should not try to make a pointer const [\#774](https://github.com/code-cracker/code-cracker/issues/774) + +**Closed issues:** + +- Verify impact of upgrading to Roslyn 1.1 [\#770](https://github.com/code-cracker/code-cracker/issues/770) + ## [v1.0.0](https://github.com/code-cracker/code-cracker/tree/v1.0.0) (2016-04-03) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0-rc6...v1.0.0) From 2eadc09a850ddf93b9cebcb6cbf6c4e5fec53780 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 6 Sep 2016 13:04:45 -0300 Subject: [PATCH 072/234] Bump version to 1.0.2 --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CSharp/CodeCracker/Properties/AssemblyInfo.cs | 2 +- src/CodeCracker.nuspec | 6 +++--- src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 2 +- src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb | 2 +- test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Test.Common/Properties/AssemblyInfo.cs | 2 +- .../VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index 19b4ff34c..96ab65b93 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for C# An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index e08549efe..cf2da4160 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.CSharp - 1.0.1 + 1.0.2 CodeCracker for C# giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs index e73618076..a2cbcaa12 100644 --- a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.2.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index c910e7aba..6ceea0773 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker - 1.0.1 + 1.0.2 CodeCracker for C# and VB giggio,elemarjr,carloscds giggio,elemarjr,carloscds @@ -19,8 +19,8 @@ This is a community project, free and open source. Everyone is invited to contri Copyright CodeCracker 2014-2016 roslyn, analyzers - - + + diff --git a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs index 8fd31cfbe..9bee0ce03 100644 --- a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs +++ b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs @@ -14,6 +14,6 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.2.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] [assembly: InternalsVisibleTo("CodeCracker.Test.VisualBasic")] \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index 2292f0dec..ddd2f9d9d 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for Visual Basic An analyzer library for VB that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index 70abb04ba..ecb28d922 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.VisualBasic - 1.0.1 + 1.0.2 CodeCracker for Visual Basic giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb index 9f6f2650c..1425d7339 100644 --- a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb +++ b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb @@ -14,5 +14,5 @@ Imports System.Runtime.InteropServices - + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs index 9da58a97d..8809cfb5b 100644 --- a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs +++ b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.0.2.0")] \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs index 8c492b358..2a6956dbe 100644 --- a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en-us")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.0.2.0")] \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb index 2599bd9f5..f7d706ba8 100644 --- a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb +++ b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb @@ -14,4 +14,4 @@ Imports System.Runtime.InteropServices - \ No newline at end of file + \ No newline at end of file From e718be3e5dd13f5fdb7b61630ae076e6355183b6 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Tue, 6 Sep 2016 16:19:36 -0300 Subject: [PATCH 073/234] Refactor UnnecessaryToStringInStringConcatenationAnalyzer --- ...ryToStringInStringConcatenationAnalyzer.cs | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs index fb9a0974a..d2c56f355 100644 --- a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs @@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -36,39 +37,28 @@ public override void Initialize(AnalysisContext context) => private static void Analyzer(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; - var addExpression = context.Node as BinaryExpressionSyntax; + var addExpression = (BinaryExpressionSyntax)context.Node; - if (!addExpression.IsKind(SyntaxKind.AddExpression)) return; - - var hasPlusToken = addExpression.ChildNodesAndTokens().Any(x => x.IsKind(SyntaxKind.PlusToken)); var hasInvocationExpression = addExpression.ChildNodesAndTokens().Any(x => x.IsKind(SyntaxKind.InvocationExpression)); - //string concatenation must have PlusToken and an InvocationExpression - if (!hasPlusToken || !hasInvocationExpression) return; + //string concatenation must have an InvocationExpression + if (!hasInvocationExpression) return; var invocationExpressionsThatHaveToStringCall = GetInvocationExpressionsThatHaveToStringCall(addExpression); foreach (var expression in invocationExpressionsThatHaveToStringCall) - { + { var lastDot = expression.Expression.ChildNodesAndTokens().Last(x => x.IsKind(SyntaxKind.DotToken)); - var argumentList = expression.ChildNodes().Last(x => x.IsKind(SyntaxKind.ArgumentList)); - - //Only default call to ToString method must be accepted - if (expression.ArgumentList.Arguments.Count > 0) - break; - - var tree = expression.SyntaxTree; - var textspan = new TextSpan(lastDot.Span.Start, argumentList.Span.End - lastDot.Span.Start); - - var diagnostic = Diagnostic.Create(Rule, Location.Create(context.Node.SyntaxTree, textspan)); + var toStringTextSpan = new TextSpan(lastDot.Span.Start, expression.ArgumentList.Span.End - lastDot.Span.Start); + var diagnostic = Diagnostic.Create(Rule, Location.Create(context.Node.SyntaxTree, toStringTextSpan)); context.ReportDiagnostic(diagnostic); } } - private static System.Collections.Generic.List GetInvocationExpressionsThatHaveToStringCall(BinaryExpressionSyntax addExpression) + private static IEnumerable GetInvocationExpressionsThatHaveToStringCall(BinaryExpressionSyntax addExpression) { return addExpression.ChildNodes().OfType() - .Where(x => x.Expression.ToString().EndsWith(@".ToString")) - .ToList(); + //Only default call to ToString method must be accepted + .Where(x => x.Expression.ToString().EndsWith(@".ToString") && !x.ArgumentList.Arguments.Any()); } } } \ No newline at end of file From e981d303edd938f2e3da422c21035d9002688119 Mon Sep 17 00:00:00 2001 From: Nozziel Date: Wed, 19 Oct 2016 21:15:26 +0200 Subject: [PATCH 074/234] #848 - "Disposable Field Not Disposed" rule does not recognize null propagation - Fix + Unit test --- .../DisposableFieldNotDisposedAnalyzer.cs | 38 ++++++++++++++++--- .../Usage/DisposableFieldNotDisposedTests.cs | 23 +++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs index 2e625e04d..b90b12001 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs @@ -92,13 +92,41 @@ private static bool CallsDisposeOnField(IFieldSymbol fieldSymbol, MethodDeclarat var hasDisposeCall = body.DescendantNodes().OfKind(SyntaxKind.InvocationExpression) .Any(invocation => { - if (!invocation?.Expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) ?? true) return false; - var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; - if (memberAccess?.Name == null) return false; - if (memberAccess.Name.Identifier.ToString() != "Dispose" || memberAccess.Name.Arity != 0) return false; - return fieldSymbol.Equals(semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol); + if (invocation?.Expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) ?? false) + { + return IsDisposeCallOnField(invocation, fieldSymbol, semanticModel); + + } + + if (invocation?.Expression?.IsKind(SyntaxKind.MemberBindingExpression) ?? false) + { + return IsDisposeWithNullPropagationCallOnField(invocation, fieldSymbol, semanticModel); + } + + return false; }); return hasDisposeCall; } + + private static bool IsDisposeCallOnField(InvocationExpressionSyntax expression, IFieldSymbol fieldSymbol, SemanticModel semanticModel) + { + var memberAccess = (MemberAccessExpressionSyntax)expression.Expression; + if (memberAccess?.Name == null) return false; + if (memberAccess.Name.Identifier.ToString() != "Dispose" || memberAccess.Name.Arity != 0) return false; + var result = fieldSymbol.Equals(semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol); + return result; + } + + private static bool IsDisposeWithNullPropagationCallOnField(InvocationExpressionSyntax expression, IFieldSymbol fieldSymbol, SemanticModel semanticModel) + { + var memberBinding = (MemberBindingExpressionSyntax)expression.Expression; + if (memberBinding?.Name == null) return false; + if (memberBinding.Name.Identifier.ToString() != "Dispose" || memberBinding.Name.Arity != 0) return false; + + var conditionalAccessExpression = memberBinding.Parent.Parent as ConditionalAccessExpressionSyntax; + if (conditionalAccessExpression == null) return false; + var result = fieldSymbol.Equals(semanticModel.GetSymbolInfo(conditionalAccessExpression.Expression).Symbol); + return result; + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs index ba84e4bc6..1c46e93f2 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs @@ -45,6 +45,29 @@ private void Dispose(bool disposing) await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task WhenUsingTheDisposablePatternWithNullPropagationItDoesNotCreateDiagnostic() + { + const string source = @" +using System; +using System.IO; +public class A : IDisposable +{ + private MemoryStream disposableField = new MemoryStream(); + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + private void Dispose(bool disposing) + { + if (disposing) + disposableField?.Dispose(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task WhenAFieldThatImplementsIDisposableIsAssignedThroughAMethodCallCreatesDiagnostic() { From dce78e2a591fcd6f58320d5a53912942d8accf96 Mon Sep 17 00:00:00 2001 From: cezar teste Date: Thu, 27 Oct 2016 11:22:35 -0200 Subject: [PATCH 075/234] - Adding test for: bool method param, int var situations,CS0151Exception and common situations with boolean variables. --- src/CSharp/CodeCracker/CodeCracker.csproj | 2 + .../Design/SwitchWithoutDefaultAnalyzer.cs | 66 ++++ .../SwitchWithoutDefaultCodeFixProvider.cs | 121 ++++++ src/Common/CodeCracker.Common/DiagnosticId.cs | 1 + .../CodeCracker.Test/CodeCracker.Test.csproj | 1 + .../Design/SwicthWithoutDefaultTests.cs | 353 ++++++++++++++++++ 6 files changed, 544 insertions(+) create mode 100644 src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs create mode 100644 src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs create mode 100644 test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 965fba6b7..8b9e64a32 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -46,6 +46,8 @@ + + diff --git a/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs new file mode 100644 index 000000000..b4531315f --- /dev/null +++ b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs @@ -0,0 +1,66 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + + +namespace CodeCracker.CSharp.Design +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class SwitchWithoutDefaultAnalyzer : DiagnosticAnalyzer + { + internal const string Title = "Your Switch maybe include default clause"; + internal const string MessageFormat = "{0}"; + internal const string Category = SupportedCategories.Design; + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId.SwitchCaseWithoutDefault.ToDiagnosticId(), + Title, + MessageFormat, + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.SwitchCaseWithoutDefault)); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) => context.RegisterSyntaxNodeAction(Analyzer, SyntaxKind.SwitchStatement); + + private static void Analyzer(SyntaxNodeAnalysisContext context) + { + if (context.IsGenerated()) return; + // checks if the compile error CS0151 it has fired.If Yes, don't report the diagnostic + var diagnostics = from dia in context.SemanticModel.GetDiagnostics() + where dia.Id == "CS0151" + select dia; + if (diagnostics.Any()) return; + if (context.Node.IsKind(SyntaxKind.SwitchStatement)) + { + var switchStatementToAnalyse = (SwitchStatementSyntax)context.Node; + if (switchStatementToAnalyse.DescendantNodes().Where(n => n.Kind() == SyntaxKind.DefaultSwitchLabel).ToList().Count == 0) + { + var hasInitializer = from nodes in switchStatementToAnalyse.DescendantNodes() + where nodes.Kind() == SyntaxKind.IdentifierName + select nodes; + if (!hasInitializer.Any()) + return; + var hasTrueExpression = from nodes in switchStatementToAnalyse.DescendantNodes() + where nodes.Kind() == SyntaxKind.FalseLiteralExpression + select nodes; + var hasfalseExpression = from nodes in switchStatementToAnalyse.DescendantNodes() + where nodes.Kind() == SyntaxKind.TrueLiteralExpression + select nodes; + if ((hasfalseExpression.Any()) && (hasTrueExpression.Any())) + return; + var diagnostic = Diagnostic.Create(Rule, switchStatementToAnalyse.GetLocation(), "Consider put an default clause in Switch."); + context.ReportDiagnostic(diagnostic); + } + } + } + } +} diff --git a/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs new file mode 100644 index 000000000..192d1ac5e --- /dev/null +++ b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs @@ -0,0 +1,121 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Formatting; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +namespace CodeCracker.CSharp.Design +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(SwitchWithoutDefaultCodeFixProvider)), Shared] + public class SwitchWithoutDefaultCodeFixProvider : CodeFixProvider + { + private const string EmptyString = "\"\""; + private const string BreakString = "\n\t\t\t\t\tbreak;"; + private const string ThrowString = "throw new Exception(\"Unexpected Case\");"; + public sealed override ImmutableArray FixableDiagnosticIds => + ImmutableArray.Create(DiagnosticId.SwitchCaseWithoutDefault.ToDiagnosticId()); + public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var diagnostic = context.Diagnostics.First(); + context.RegisterCodeFix(CodeAction.Create("Add a default clause", c => SwitchWithoutDefaultAsync(context.Document, diagnostic, c), + nameof(SwitchWithoutDefaultCodeFixProvider)), diagnostic); + return Task.FromResult(0); + } + + private async static Task SwitchWithoutDefaultAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var switchCaseLabel = new SyntaxList(); + var kindOfVariable = string.Empty; + var idForVariable = string.Empty; + var breakStatement = new SyntaxList(); + var diagnosticSpan = diagnostic.Location.SourceSpan; + var newSections = new List(); + var switchCaseStatement = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); + idForVariable = ((IdentifierNameSyntax)switchCaseStatement.ChildNodes().ToList().First(n => n.Kind() == SyntaxKind.IdentifierName)).Identifier.ValueText; + var parametersOfMethod = from init in root.DescendantNodesAndSelf() + where init.Kind() == SyntaxKind.Parameter + select init; + // Verify if the variable of Switch as a same of Method Parameter + foreach (var parameter in parametersOfMethod) + if (idForVariable == ((ParameterSyntax)parameter).Identifier.ValueText) + kindOfVariable = ((ParameterSyntax)parameter).Type.ToString(); + + if (kindOfVariable == string.Empty) + { + var statements = ((BlockSyntax)switchCaseStatement.Parent).Statements; + var inicializerOfSwitch = from init in statements + where init.Kind() == SyntaxKind.LocalDeclarationStatement + select init; + if (inicializerOfSwitch.Any()) + { + var local = (LocalDeclarationStatementSyntax)inicializerOfSwitch.First(); + var switchCaseVariable = ((local).Declaration).Variables[0]; + kindOfVariable = ((LiteralExpressionSyntax)(switchCaseVariable.Initializer.Value)).Kind().ToString(); + } + } + + if ((kindOfVariable.Equals("FalseLiteralExpression")) || (kindOfVariable.Equals("TrueLiteralExpression")) + || (kindOfVariable.Equals("bool"))) + { + var oldSections = switchCaseStatement.Sections.ToList(); + var type = string.Empty; + foreach (var sec in oldSections) + { + newSections.Add(sec); + type = (((CaseSwitchLabelSyntax)((SwitchSectionSyntax)sec).ChildNodes().ToList().First()).Value).GetFirstToken().Text; + } + var againstType = string.Empty; + if (type.Equals("true")) againstType = "false"; else againstType = "true"; + + newSections.Add(SyntaxFactory.SwitchSection().WithLabels( + switchCaseLabel.Add(SyntaxFactory.CaseSwitchLabel(SyntaxFactory.ParseExpression(againstType)))). + WithStatements(breakStatement.Add(SyntaxFactory.ParseStatement(BreakString)))); + } + else + { + var oldSections = switchCaseStatement.Sections.ToList(); + foreach (var sec in oldSections) + newSections.Add(sec); + + breakStatement = breakStatement.Add(SyntaxFactory.ParseStatement(BreakString)); + newSections.Add(CreateSection(SyntaxFactory.DefaultSwitchLabel(), SyntaxFactory.ParseStatement(ThrowString))); + } + var switchExpression = SyntaxFactory.ParseExpression(idForVariable); + var newsSwitchCaseStatement = SyntaxFactory.SwitchStatement(switchExpression). + WithSections(new SyntaxList().AddRange(newSections)); + var newRoot = root.ReplaceNode(switchCaseStatement, newsSwitchCaseStatement); + var newDocument = document.WithSyntaxRoot(newRoot); + return newDocument; + } + static SwitchSectionSyntax CreateSection(SwitchLabelSyntax label, StatementSyntax statement) + { + var labels = new SyntaxList(); + labels = labels.Add(label); + return SyntaxFactory.SwitchSection(labels, CreateSectionStatements(statement)); + } + + static SyntaxList CreateSectionStatements(StatementSyntax source) + { + var result = new SyntaxList(); + if (source is BlockSyntax) + { + var block = source as BlockSyntax; + result = result.AddRange(block.Statements); + } + else + { + result = result.Add(source); + } + return result; + } + } +} diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index 7d48257fd..1ac3b7f5e 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -81,5 +81,6 @@ public enum DiagnosticId StringFormatArgs_ExtraArgs = 111, AlwaysUseVarOnPrimitives = 105, UnnecessaryToStringInStringConcatenation = 118, + SwitchCaseWithoutDefault = 120, } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 7168f11df..915d2199d 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -129,6 +129,7 @@ + diff --git a/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs b/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs new file mode 100644 index 000000000..c9fa24b44 --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs @@ -0,0 +1,353 @@ +using CodeCracker.CSharp.Design; +using System.Threading.Tasks; +using Xunit; + +namespace CodeCracker.Test.CSharp.Design +{ + public class SwicthWithoutDefaultTests : CodeFixVerifier + { + [Fact] + public async Task SwithWithoutDefaultAnalyserString() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { +var a = """"; + switch (a) + { + case """": + break; + } + } + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { +var a = """"; + switch (a) + { + case """": + break; + default: + throw new Exception(""Unexpected Case""); + } + } + } + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + } + + [Fact] + public async Task SwithWithoutDefaultAnalyserBool() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { + var s = true; + switch (s) + { + case false: + break; + } + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { + var s = true; + switch (s) + { + case false: + break; + case true: + break; + } + } + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + } + + [Fact] + public async Task SwithWithoutDefaultAnalyserInt() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { +var s = 10; + switch (s) + { + case 10: + break; + } + +} + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { +var s = 10; + switch (s) + { + case 10: + break; + default: + throw new Exception(""Unexpected Case""); + } + } +} + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + + } + + public async Task SwithWithoutDefaultAnalyserBoolMethod() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + void Bar(bool myBool) + { + switch (myBool) + { + case false: + break; + } + } + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + void Bar(bool myBool) + { + switch (myBool) + { + case false: + break; + case true: + break; + } + } + + } + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + } + + public async Task SwithWithoutDefaultAnalyserIntMethod() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + void Bar3(int a) + { + switch (a) + { + case 10: + break; + } + } + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + void Bar3(int a) + { + switch (a) + { + case 10: + break; + default: + throw new Exception(""Unexpected Case""); + } + } +} + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + } + + public async Task SwithWithoutDefaultAnalyserIntMethodTwoParams() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { +void Bar4(int a, int b) + { + switch (a) + { + case 10: + break; + } + } + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { +void Bar4(int a, int b) + { + switch (a) + { + case 10: + break; + default: + throw new Exception(""Unexpected Case""); + } + } +} + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + } + + [Fact] + public async Task SwithWithoutDefaultAnalyserIntMethodStatic() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { +static void Bar5(int a) + { + switch (a) + { + case 10: + break; + } + } + + } + }"; + + const string fixtest = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { +static void Bar5(int a) + { + switch (a) + { + case 10: + break; + default: + throw new Exception(""Unexpected Case""); + } + } + +} + }"; + await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + } + + [Fact] + public async Task SwithWithoutDefaultAnalyseCS0151Exception() + { + const string source = @"static void M() { } + static void Main() + { + + switch (M()) // CS0151 + { + default: + break; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + + [Fact] + public async Task SwithWithoutDefaultAnalyserNoDiagnostic() + { + const string source = @"using System;namespace + ConsoleApplication1 + { + class TypeName + { + static void Main() + { + var s = ""; + switch (s) + { + case "":{break;} + default:{break;} + } + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task SwitchWithoutDefaultAnalyzerNoDiagnosticWithCompileError() + { + const string source = @"using System; + namespace ConsoleApplication1 + { + ConsoleApplication1 + { + class Teste { } + class Program + { + static void Main(string[] args) + { + Teste vo_teste = new Teste(); + switch (vo_teste) + { + case "":break; + default:break; + } + } + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + } +} From 5729fe362e47fab5492bdb6fb0ec2e7449c7d7a8 Mon Sep 17 00:00:00 2001 From: cezar teste Date: Tue, 22 Nov 2016 10:08:18 -0200 Subject: [PATCH 076/234] Fix #808 Added the suggested changes in Title and Description on ReadOnlyComplexTypesAnalyzer --- src/CSharp/CodeCracker/CodeCracker.csproj | 1 + .../Usage/ReadOnlyComplexTypesAnalyzer.cs | 69 +++ .../Usage/ReadonlyFieldCodeFixProvider.cs | 3 +- src/Common/CodeCracker.Common/DiagnosticId.cs | 1 + .../CodeCracker.Test/CodeCracker.Test.csproj | 1 + .../Usage/ReadOnlyComplexTypesTests.cs | 441 ++++++++++++++++++ 6 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 src/CSharp/CodeCracker/Usage/ReadOnlyComplexTypesAnalyzer.cs create mode 100644 test/CSharp/CodeCracker.Test/Usage/ReadOnlyComplexTypesTests.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 8b9e64a32..da195cbf0 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -139,6 +139,7 @@ + diff --git a/src/CSharp/CodeCracker/Usage/ReadOnlyComplexTypesAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadOnlyComplexTypesAnalyzer.cs new file mode 100644 index 000000000..089013936 --- /dev/null +++ b/src/CSharp/CodeCracker/Usage/ReadOnlyComplexTypesAnalyzer.cs @@ -0,0 +1,69 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using System.Collections.Immutable; +using System.Linq; +using System.Collections.Generic; +using System; + +namespace CodeCracker.CSharp.Usage +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class ReadOnlyComplexTypesAnalyzer : DiagnosticAnalyzer + { + internal const string Title = "Complex fields must be readonly"; + internal const string Message = "Make '{0}' readonly"; + internal const string Category = SupportedCategories.Usage; + const string Description = "Complex fields must be readonly"; + + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId.ReadOnlyComplexTypes.ToDiagnosticId(), + Title, + Message, + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: false, + description: Description, + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.ReadOnlyComplexTypes)); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) => context.RegisterSyntaxNodeAction(AnalyzeNode, + new[] { SyntaxKind.FieldDeclaration }); + + private static void AnalyzeNode(SyntaxNodeAnalysisContext context) + { + if (context.IsGenerated()) return; + var fieldDeclaration = context.Node as FieldDeclarationSyntax; + var variable = fieldDeclaration?.Declaration.Variables.LastOrDefault(); + if (variable?.Initializer == null) return; + var semanticModel = context.SemanticModel; + var fieldSymbol = semanticModel.GetDeclaredSymbol(variable) as IFieldSymbol; + if (!IsComplexValueType(semanticModel, fieldDeclaration)) return; + if (!CanBeMadeReadonly(fieldSymbol)) return; + ReportDiagnostic(context, variable, variable.Initializer.Value); + } + private static bool IsComplexValueType(SemanticModel semanticModel, FieldDeclarationSyntax fieldDeclaration) + { + var fieldTypeName = fieldDeclaration.Declaration.Type; + var fieldType = semanticModel.GetTypeInfo(fieldTypeName).ConvertedType; + return fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + } + + private static bool CanBeMadeReadonly(IFieldSymbol fieldSymbol) + { + return (fieldSymbol.DeclaredAccessibility == Accessibility.NotApplicable + || fieldSymbol.DeclaredAccessibility == Accessibility.Private) + && !fieldSymbol.IsReadOnly + && !fieldSymbol.IsConst; + } + + private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, VariableDeclaratorSyntax variable, ExpressionSyntax initializerValue) + { + var props = new Dictionary { { "identifier", variable.Identifier.Text } }.ToImmutableDictionary(); + var diag = Diagnostic.Create(Rule, variable.GetLocation(), props, initializerValue.ToString()); + context.ReportDiagnostic(diag); + } + } +} diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldCodeFixProvider.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldCodeFixProvider.cs index 9b0d0be1a..1b9e85a58 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldCodeFixProvider.cs @@ -16,7 +16,8 @@ namespace CodeCracker.CSharp.Usage public class ReadonlyFieldCodeFixProvider : CodeFixProvider { public sealed override ImmutableArray FixableDiagnosticIds => - ImmutableArray.Create(DiagnosticId.ReadonlyField.ToDiagnosticId()); + ImmutableArray.Create(DiagnosticId.ReadonlyField.ToDiagnosticId(), + DiagnosticId.ReadOnlyComplexTypes.ToDiagnosticId()); public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index 1ac3b7f5e..e60eb36f8 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -82,5 +82,6 @@ public enum DiagnosticId AlwaysUseVarOnPrimitives = 105, UnnecessaryToStringInStringConcatenation = 118, SwitchCaseWithoutDefault = 120, + ReadOnlyComplexTypes = 121, } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 915d2199d..aa793b0cd 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -172,6 +172,7 @@ + diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadOnlyComplexTypesTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadOnlyComplexTypesTests.cs new file mode 100644 index 000000000..d6fe05fb9 --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Usage/ReadOnlyComplexTypesTests.cs @@ -0,0 +1,441 @@ +using CodeCracker.CSharp.Usage; +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace CodeCracker.Test.CSharp.Usage +{ + public class ReadOnlyComplexTypesTests : CodeFixVerifier + { + [Fact] + public async Task FieldWithAssignmentOnDeclarationAlreadyReadonlyDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + class TypeName + { + private readonly int i = 1; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task ConstantFieldDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + class TypeName + { + private const int i = 1; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task dateTimeDoesNotCreateDiagnostics() + { + const string source1 = @" +namespace codeCrackerConsole +{ + public class MyClass + { + private readonly DateTime dt = new DateTime(1, 1, 2015); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source1); + } + [Fact] + public async Task protectedFieldDoesNotCreateDiagnostics() + { + const string source = @" + namespace ConsoleApplication1 + { +public class MyClass + { + protected MyStruct myStruct = default(MyStruct); + private struct MyStruct + { + public int Value; + } + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task publicFieldDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + public MyStruct myStruct = default(MyStruct); + private struct MyStruct + { + public int Value; + } + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task publicFieldWithClassDoesNotCreateDiagnostics() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + public MyStruct myStruct = new MyStruct(); + private struct MyStruct + { + public int Value; + } + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task readOnlyVarDoesNotCreateDiagnostics() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + readonly var s = ""; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task readOnlyFieldDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + readonly string s; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task primitiveTypesDoesNotCreateDiagnostics() + { + const string source = @" + namespace ConsoleApplication1 + { + class test + { + private byte b = new byte(); + private sbyte s = new sbyte(); + private int i = new int(); + private uint u = new uint(); + private short ss = new short(); + public ushort us = new ushort(); + public long l = new long(); + public ulong ul = new ulong(); + public float fl = new float(); + public double d = new double(); + public char c = new char(); + public bool bo = new bool(); + public object o = new object(); + public string st = ""; + public decimal dc = new decimal(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task enumDoesNotCreateDiagnostics() + { + const string source = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private test testEnum; + public enum test + { + test1 = 1, + test2 = 2 + } + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + [Fact] + public async Task IgnoreOut() + { + const string source = @" +public class C +{ + private string field = ""; + private static void Foo(out string bar) => bar = ""; + public void Baz() => Foo(out field); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task IgnoreRef() + { + const string source = @" +public class C +{ + private string field = ""; + private static void Foo(ref string bar) => bar = ""; + public void Baz() => Foo(ref field); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task IgnoreAssignmentToFieldsInOtherTypes() + { + const string source1 = @" +class TypeName1 +{ + public int i; +}"; + const string source2 = @" +class TypeName2 +{ + public TypeName2() + { + var t = new TypeName1(); + t.i = 1; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source1, source2 }); + } + + [Fact] + public async Task FieldWithoutAssignmentDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + class TypeName + { + private int i; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task FieldWithoutAssignmentInAStructDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + struct TypeName + { + private int i; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task PublicFieldWithAssignmentOnDeclarationDoesNotCreateDiagnostic() + { + const string source = @" + namespace ConsoleApplication1 + { + class TypeName + { + public int i = 1; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + + [Fact] + public async Task structNoDiagnostic() + { + const string source1 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct; + private struct MyStruct + { + public int Value; + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source1 }); + } + + [Fact] + public async Task structWithNullValue() + { + const string source1 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct = null; + private struct MyStruct + { + public int Value; + } + } + }"; + const string source2 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private readonly MyStruct myStruct = null; + private struct MyStruct + { + public int Value; + } + } + }"; + await VerifyCSharpFixAsync(source1, source2, 0); + } + [Fact] + public async Task structDefaultCreateWithoutReadOnlyDeclarationSameClass() + { + const string source1 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct = default(MyStruct); + private struct MyStruct + { + public int Value; + } + } + }"; + const string source2 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private readonly MyStruct myStruct = default(MyStruct); + private struct MyStruct + { + public int Value; + } + } + }"; + await VerifyCSharpFixAsync(source1, source2, 0); + } + + [Fact] + public async Task structCreateWithoutReadonlyDeclaration() + { + const string source1 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct = new MyStruct(); + } + private struct MyStruct + { + public int Value; + } + }"; + const string source2 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private readonly MyStruct myStruct = new MyStruct(); + } + private struct MyStruct + { + public int Value; + } + }"; + await VerifyCSharpFixAsync(source1, source2, 0); + } + + [Fact] + public async Task structDefaultCreateWithoutReadonlyDeclaration() + { + const string source1 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private MyStruct myStruct = default(MyStruct); + } + private struct MyStruct + { + public int Value; + } + }"; + const string source2 = @" + namespace ConsoleApplication1 + { + public class MyClass + { + private readonly MyStruct myStruct = default(MyStruct); + } + private struct MyStruct + { + public int Value; + } + }"; + await VerifyCSharpFixAsync(source1, source2, 0); + } + [Fact] + public async Task enumerationsDoesNotCreateDiagnostic() + { + const string source = @" + public class EnumTest + { + enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }; + + static void Main() + { + int x = (int)Days.Sun; + int y = (int)Days.Fri; + int z = x + y; + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + + [Fact] + public async Task privateEnumerationsDoesNotCreateDiagnostic() + { + const string source = @" + public class EnumTest + { + enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }; + private Days enumDays; + static void Main() + { + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(new[] { source }); + } + } +} From cfa4fa358c3b0622fb2f06741461f041802bc55f Mon Sep 17 00:00:00 2001 From: Nozziel Date: Wed, 19 Oct 2016 21:15:26 +0200 Subject: [PATCH 077/234] #848 - "Disposable Field Not Disposed" rule does not recognize null propagation - Fix + Unit test --- .../DisposableFieldNotDisposedAnalyzer.cs | 38 ++++++++++++++++--- .../Usage/DisposableFieldNotDisposedTests.cs | 23 +++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs index 2e625e04d..b90b12001 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableFieldNotDisposedAnalyzer.cs @@ -92,13 +92,41 @@ private static bool CallsDisposeOnField(IFieldSymbol fieldSymbol, MethodDeclarat var hasDisposeCall = body.DescendantNodes().OfKind(SyntaxKind.InvocationExpression) .Any(invocation => { - if (!invocation?.Expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) ?? true) return false; - var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; - if (memberAccess?.Name == null) return false; - if (memberAccess.Name.Identifier.ToString() != "Dispose" || memberAccess.Name.Arity != 0) return false; - return fieldSymbol.Equals(semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol); + if (invocation?.Expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) ?? false) + { + return IsDisposeCallOnField(invocation, fieldSymbol, semanticModel); + + } + + if (invocation?.Expression?.IsKind(SyntaxKind.MemberBindingExpression) ?? false) + { + return IsDisposeWithNullPropagationCallOnField(invocation, fieldSymbol, semanticModel); + } + + return false; }); return hasDisposeCall; } + + private static bool IsDisposeCallOnField(InvocationExpressionSyntax expression, IFieldSymbol fieldSymbol, SemanticModel semanticModel) + { + var memberAccess = (MemberAccessExpressionSyntax)expression.Expression; + if (memberAccess?.Name == null) return false; + if (memberAccess.Name.Identifier.ToString() != "Dispose" || memberAccess.Name.Arity != 0) return false; + var result = fieldSymbol.Equals(semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol); + return result; + } + + private static bool IsDisposeWithNullPropagationCallOnField(InvocationExpressionSyntax expression, IFieldSymbol fieldSymbol, SemanticModel semanticModel) + { + var memberBinding = (MemberBindingExpressionSyntax)expression.Expression; + if (memberBinding?.Name == null) return false; + if (memberBinding.Name.Identifier.ToString() != "Dispose" || memberBinding.Name.Arity != 0) return false; + + var conditionalAccessExpression = memberBinding.Parent.Parent as ConditionalAccessExpressionSyntax; + if (conditionalAccessExpression == null) return false; + var result = fieldSymbol.Equals(semanticModel.GetSymbolInfo(conditionalAccessExpression.Expression).Symbol); + return result; + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs index ba84e4bc6..1c46e93f2 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs @@ -45,6 +45,29 @@ private void Dispose(bool disposing) await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task WhenUsingTheDisposablePatternWithNullPropagationItDoesNotCreateDiagnostic() + { + const string source = @" +using System; +using System.IO; +public class A : IDisposable +{ + private MemoryStream disposableField = new MemoryStream(); + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + private void Dispose(bool disposing) + { + if (disposing) + disposableField?.Dispose(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task WhenAFieldThatImplementsIDisposableIsAssignedThroughAMethodCallCreatesDiagnostic() { From e1c18b6be36ce56e3f84e6f3c6f0b2cfdda7a68f Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 7 Jan 2017 16:40:28 -0200 Subject: [PATCH 078/234] Fix bug on CC0120 when there was a conversion Also major refactors Fixes #859 --- .../Design/SwitchWithoutDefaultAnalyzer.cs | 10 +- .../SwitchWithoutDefaultCodeFixProvider.cs | 71 ++---- .../Design/SwicthWithoutDefaultTests.cs | 208 ++++++++++-------- 3 files changed, 142 insertions(+), 147 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs index b4531315f..82a31165c 100644 --- a/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultAnalyzer.cs @@ -47,16 +47,14 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) var hasInitializer = from nodes in switchStatementToAnalyse.DescendantNodes() where nodes.Kind() == SyntaxKind.IdentifierName select nodes; - if (!hasInitializer.Any()) - return; + if (!hasInitializer.Any()) return; var hasTrueExpression = from nodes in switchStatementToAnalyse.DescendantNodes() - where nodes.Kind() == SyntaxKind.FalseLiteralExpression + where nodes.IsKind(SyntaxKind.FalseLiteralExpression) select nodes; var hasfalseExpression = from nodes in switchStatementToAnalyse.DescendantNodes() - where nodes.Kind() == SyntaxKind.TrueLiteralExpression + where nodes.IsKind(SyntaxKind.TrueLiteralExpression) select nodes; - if ((hasfalseExpression.Any()) && (hasTrueExpression.Any())) - return; + if (hasfalseExpression.Any() && hasTrueExpression.Any()) return; var diagnostic = Diagnostic.Create(Rule, switchStatementToAnalyse.GetLocation(), "Consider put an default clause in Switch."); context.ReportDiagnostic(diagnostic); } diff --git a/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs index 192d1ac5e..086dd9055 100644 --- a/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Design/SwitchWithoutDefaultCodeFixProvider.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Simplification; using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; @@ -15,9 +16,6 @@ namespace CodeCracker.CSharp.Design [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(SwitchWithoutDefaultCodeFixProvider)), Shared] public class SwitchWithoutDefaultCodeFixProvider : CodeFixProvider { - private const string EmptyString = "\"\""; - private const string BreakString = "\n\t\t\t\t\tbreak;"; - private const string ThrowString = "throw new Exception(\"Unexpected Case\");"; public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.SwitchCaseWithoutDefault.ToDiagnosticId()); public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; @@ -33,69 +31,32 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) private async static Task SwitchWithoutDefaultAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var switchCaseLabel = new SyntaxList(); - var kindOfVariable = string.Empty; - var idForVariable = string.Empty; - var breakStatement = new SyntaxList(); - var diagnosticSpan = diagnostic.Location.SourceSpan; var newSections = new List(); - var switchCaseStatement = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - idForVariable = ((IdentifierNameSyntax)switchCaseStatement.ChildNodes().ToList().First(n => n.Kind() == SyntaxKind.IdentifierName)).Identifier.ValueText; - var parametersOfMethod = from init in root.DescendantNodesAndSelf() - where init.Kind() == SyntaxKind.Parameter - select init; - // Verify if the variable of Switch as a same of Method Parameter - foreach (var parameter in parametersOfMethod) - if (idForVariable == ((ParameterSyntax)parameter).Identifier.ValueText) - kindOfVariable = ((ParameterSyntax)parameter).Type.ToString(); - - if (kindOfVariable == string.Empty) - { - var statements = ((BlockSyntax)switchCaseStatement.Parent).Statements; - var inicializerOfSwitch = from init in statements - where init.Kind() == SyntaxKind.LocalDeclarationStatement - select init; - if (inicializerOfSwitch.Any()) - { - var local = (LocalDeclarationStatementSyntax)inicializerOfSwitch.First(); - var switchCaseVariable = ((local).Declaration).Variables[0]; - kindOfVariable = ((LiteralExpressionSyntax)(switchCaseVariable.Initializer.Value)).Kind().ToString(); - } - } - - if ((kindOfVariable.Equals("FalseLiteralExpression")) || (kindOfVariable.Equals("TrueLiteralExpression")) - || (kindOfVariable.Equals("bool"))) + var switchCaseStatement = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); + var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var expressionSymbol = semanticModel.GetSymbolInfo(switchCaseStatement.Expression).Symbol; + if (semanticModel.GetTypeInfo(switchCaseStatement.Expression).Type.SpecialType == SpecialType.System_Boolean) { - var oldSections = switchCaseStatement.Sections.ToList(); - var type = string.Empty; - foreach (var sec in oldSections) - { - newSections.Add(sec); - type = (((CaseSwitchLabelSyntax)((SwitchSectionSyntax)sec).ChildNodes().ToList().First()).Value).GetFirstToken().Text; - } - var againstType = string.Empty; - if (type.Equals("true")) againstType = "false"; else againstType = "true"; - + var type = ((CaseSwitchLabelSyntax)switchCaseStatement.Sections.Last().ChildNodes().First()).Value.GetFirstToken().Text; + var againstType = type == "true" ? "false" : "true"; newSections.Add(SyntaxFactory.SwitchSection().WithLabels( - switchCaseLabel.Add(SyntaxFactory.CaseSwitchLabel(SyntaxFactory.ParseExpression(againstType)))). - WithStatements(breakStatement.Add(SyntaxFactory.ParseStatement(BreakString)))); + new SyntaxList().Add(SyntaxFactory.CaseSwitchLabel(SyntaxFactory.ParseExpression(againstType)))) + .WithStatements(new SyntaxList().Add(SyntaxFactory.ParseStatement("break;")))); } else { - var oldSections = switchCaseStatement.Sections.ToList(); - foreach (var sec in oldSections) - newSections.Add(sec); - - breakStatement = breakStatement.Add(SyntaxFactory.ParseStatement(BreakString)); - newSections.Add(CreateSection(SyntaxFactory.DefaultSwitchLabel(), SyntaxFactory.ParseStatement(ThrowString))); + newSections.Add(CreateSection(SyntaxFactory.DefaultSwitchLabel(), + SyntaxFactory.ThrowStatement(SyntaxFactory.ObjectCreationExpression(SyntaxFactory.ParseTypeName("System.Exception").WithAdditionalAnnotations(Simplifier.Annotation), + SyntaxFactory.ArgumentList(new SeparatedSyntaxList().Add(SyntaxFactory.Argument(SyntaxFactory.ParseExpression("\"Unexpected Case\"")))), null)))); } - var switchExpression = SyntaxFactory.ParseExpression(idForVariable); - var newsSwitchCaseStatement = SyntaxFactory.SwitchStatement(switchExpression). - WithSections(new SyntaxList().AddRange(newSections)); + var newsSwitchCaseStatement = switchCaseStatement + .AddSections(newSections.ToArray()) + .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(switchCaseStatement, newsSwitchCaseStatement); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; } + static SwitchSectionSyntax CreateSection(SwitchLabelSyntax label, StatementSyntax statement) { var labels = new SyntaxList(); diff --git a/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs b/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs index c9fa24b44..88d7a4cc8 100644 --- a/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/SwicthWithoutDefaultTests.cs @@ -9,49 +9,49 @@ public class SwicthWithoutDefaultTests : CodeFixVerifier 1; +}"; + + const string fixtest = @" +using System; +class TypeName +{ + void Bar() + { + var t = new TypeName(); + switch ((int)t) + { + case 1: break; + default: + throw new Exception(""Unexpected Case""); + } + } + public static explicit operator int(TypeName v) => 1; +}"; + await VerifyCSharpFixAsync(source, fixtest); } + [Fact] public async Task SwithWithoutDefaultAnalyserIntMethodTwoParams() { - const string source = @"using System;namespace - ConsoleApplication1 + const string source = @"using System;namespace + ConsoleApplication1 { class TypeName { @@ -218,17 +255,17 @@ void Bar4(int a, int b) switch (a) { case 10: - break; + break; } } } }"; - const string fixtest = @"using System;namespace - ConsoleApplication1 + const string fixtest = @"using System;namespace + ConsoleApplication1 { class TypeName - { + { void Bar4(int a, int b) { switch (a) @@ -241,14 +278,14 @@ void Bar4(int a, int b) } } }"; - await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + await VerifyCSharpFixAsync(source, fixtest); } [Fact] public async Task SwithWithoutDefaultAnalyserIntMethodStatic() { - const string source = @"using System;namespace - ConsoleApplication1 + const string source = @"using System;namespace + ConsoleApplication1 { class TypeName { @@ -257,18 +294,18 @@ static void Bar5(int a) switch (a) { case 10: - break; + break; } } } }"; - const string fixtest = @"using System;namespace - ConsoleApplication1 + const string fixtest = @"using System;namespace + ConsoleApplication1 { class TypeName - { + { static void Bar5(int a) { switch (a) @@ -282,7 +319,7 @@ static void Bar5(int a) } }"; - await VerifyCSharpFixAsync(source, fixtest, 0, allowNewCompilerDiagnostics: true); + await VerifyCSharpFixAsync(source, fixtest); } [Fact] @@ -291,7 +328,6 @@ public async Task SwithWithoutDefaultAnalyseCS0151Exception() const string source = @"static void M() { } static void Main() { - switch (M()) // CS0151 { default: @@ -305,8 +341,8 @@ static void Main() [Fact] public async Task SwithWithoutDefaultAnalyserNoDiagnostic() { - const string source = @"using System;namespace - ConsoleApplication1 + const string source = @"using System;namespace + ConsoleApplication1 { class TypeName { @@ -329,25 +365,25 @@ public async Task SwitchWithoutDefaultAnalyzerNoDiagnosticWithCompileError() { const string source = @"using System; namespace ConsoleApplication1 - { - ConsoleApplication1 + { + ConsoleApplication1 { class Teste { } class Program { static void Main(string[] args) { - Teste vo_teste = new Teste(); + Teste vo_teste = new Teste(); switch (vo_teste) { - case "":break; + case "":break; default:break; } } - } - } + } + } }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } } -} +} \ No newline at end of file From af13035fbed3fb7bf7c60044773cf6cd78571c92 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 8 Jan 2017 03:06:34 -0200 Subject: [PATCH 079/234] Do not offer initializer for dynamic objects (CC0008) Fixes #837 Signed-off-by: Giovanni Bassi --- .../CodeCracker/Style/ObjectInitializerAnalyzer.cs | 1 + .../CodeCracker.Test/Style/ObjectInitializerTests.cs | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/CSharp/CodeCracker/Style/ObjectInitializerAnalyzer.cs b/src/CSharp/CodeCracker/Style/ObjectInitializerAnalyzer.cs index 5dc26127d..4e67acf8b 100644 --- a/src/CSharp/CodeCracker/Style/ObjectInitializerAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/ObjectInitializerAnalyzer.cs @@ -76,6 +76,7 @@ private static void AnalyzeLocalDeclaration(SyntaxNodeAnalysisContext context) if (equalsValueClauseSyntax?.Value.IsNotKind(SyntaxKind.ObjectCreationExpression) ?? true) return; if (((ObjectCreationExpressionSyntax)equalsValueClauseSyntax.Value).Initializer?.IsKind(SyntaxKind.CollectionInitializerExpression) ?? false) return; var variableSymbol = semanticModel.GetDeclaredSymbol(variable); + if (((ILocalSymbol)variableSymbol).Type.TypeKind == TypeKind.Dynamic) return; var assignmentExpressionStatements = FindAssignmentExpressions(semanticModel, localDeclarationStatement, variableSymbol); if (!assignmentExpressionStatements.Any()) return; if (HasAssignmentUsingDeclaredVariable(semanticModel, variableSymbol, assignmentExpressionStatements)) return; diff --git a/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs b/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs index b4e1b5ddb..eacb34d86 100644 --- a/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ObjectInitializerTests.cs @@ -7,6 +7,17 @@ namespace CodeCracker.Test.CSharp.Style { public class ObjectInitializerWithLocalDeclarationTests : CodeFixVerifier { + [Fact] + public async Task WhenDeclaringADynamicVariableDoesNotCreateDiagnostic() + { + var source = @" +dynamic p = new Person(); +p.Name = ""Giovanni""; +p.Age = 25; +"; + await VerifyCSharpHasNoDiagnosticsAsync(source.WrapInCSharpMethod()); + } + [Fact] public async Task WhenAssigningButNotCreatingAnalyzerDoesNotCreateDiagnostic() { From 0055881018d2275e54ad395afe53da1f462a733e Mon Sep 17 00:00:00 2001 From: bergarces Date: Wed, 14 Dec 2016 20:57:20 +0000 Subject: [PATCH 080/234] Fixed bug that prevented a non-simple assignment to appear on the If whilst a simple assignment was on the Else. Also allows different non-simple assignments on both if and else. --- .../Style/TernaryOperatorCodeFixProviders.vb | 8 +- .../Style/TernaryOperatorTests.vb | 104 ++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb index 4b60a321e..9ef918ddf 100644 --- a/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb +++ b/src/VisualBasic/CodeCracker/Style/TernaryOperatorCodeFixProviders.vb @@ -112,7 +112,7 @@ Namespace Style EnsureNothingAsType(semanticModel, type, typeSyntax). ConvertToBaseType(elseType, type) - If ifAssign.OperatorToken.Text <> "=" Then + If ifAssign.OperatorToken.Text <> "=" AndAlso ifAssign.OperatorToken.Text = elseAssign.OperatorToken.Text Then trueExpression = ifAssign.Right. EnsureNothingAsType(semanticModel, type, typeSyntax). ConvertToBaseType(ifType, type) @@ -136,7 +136,11 @@ Namespace Style trueExpression.WithoutTrailingTrivia(), falseExpression.WithoutTrailingTrivia()) - Dim assignment = SyntaxFactory.SimpleAssignmentStatement(ifAssign.Left.WithLeadingTrivia(leadingTrivia), ifAssign.OperatorToken, ternary). + Dim ternaryOperatorToken As SyntaxToken = If((ifAssign.OperatorToken.Text <> "=" OrElse elseAssign.OperatorToken.Text <> "=") AndAlso ifAssign.OperatorToken.Text <> elseAssign.OperatorToken.Text, + SyntaxFactory.Token(SyntaxKind.EqualsToken), + ifAssign.OperatorToken) + + Dim assignment = SyntaxFactory.SimpleAssignmentStatement(ifAssign.Left.WithLeadingTrivia(leadingTrivia), ternaryOperatorToken, ternary). WithTrailingTrivia(trailingTrivia). WithAdditionalAnnotations(Formatter.Annotation) diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index d5357ee71..e773cb2a7 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -438,6 +438,84 @@ End Class" Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) End Function + + Public Async Function WhenUsingConcatenationAssignmentOnIfAssignExpandsToConcatenateAtEndOfTernary() As Task + Const source = " +Public Class MyType + Public Sub Foo() + Dim x = ""test"" + If True Then + x &= ""1"" + Else + x = ""2"" + End If + End Sub +End Class" + + Const fix = " +Public Class MyType + Public Sub Foo() + Dim x = ""test"" + x = If(True, x & ""1"", ""2"") + End Sub +End Class" + + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function + + + Public Async Function WhenUsingAddAssiginmentOnIfAssignExpandsOperationProperly() As Task + Const source = " +Public Class MyType + Public Sub Foo() + Dim x = 0 + If True Then + x += 1 + Else + x = 1 + End If + End Sub +End Class" + + Const fix = " +Public Class MyType + Public Sub Foo() + Dim x = 0 + x = If(True, x + 1, 1) + End Sub +End Class" + + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function + + + Public Async Function WhenUsingSubtractAssiginmentOnIfAssignExpandsOperationProperly() As Task + Const source = " +Public Class MyType + Public Sub Foo() + Dim x = 0 + If True Then + x -= 1 + Else + x = 1 + End If + End Sub +End Class" + + Const fix = " +Public Class MyType + Public Sub Foo() + Dim x = 0 + x = If(True, x - 1, 1) + End Sub +End Class" + + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function + Public Async Function WhenUsingAssignmentOperatorReturnSameAssignment() As Task Const source = " @@ -466,6 +544,32 @@ End Class" Await VerifyBasicFixAsync(source, fix, formatBeforeCompare:=True) End Function + + + Public Async Function WhenUsingDifferentAssiginmentsExpandsOperationProperly() As Task + Const source = " +Public Class MyType + Public Sub Foo() + Dim x = 0 + If True Then + x += 1 + Else + x -= 1 + End If + End Sub +End Class" + + Const fix = " +Public Class MyType + Public Sub Foo() + Dim x = 0 + x = If(True, x + 1, x - 1) + End Sub +End Class" + + ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. + Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + End Function End Class Public Class TernaryOperatorWithReturnTests From 50208726bcabf414109ee25540ffcbd4c47d154d Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 8 Jan 2017 14:23:07 -0200 Subject: [PATCH 081/234] Update TernaryOperatorTests to remove unnecessary allowNewCompilerDiagnostics Also added 2 new tests Fixes #798 --- .../Style/TernaryOperatorTests.vb | 83 ++++++++++++------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index e773cb2a7..4e1c8a3a2 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -372,7 +372,6 @@ Public Class MyType End If End Sub End Class" - Const fix = " Public Class MyType Public Sub Foo() @@ -380,12 +379,9 @@ Public Class MyType x = If(True, ""1"", x & ""2"") End Sub End Class" - - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + Await VerifyBasicFixAsync(source, fix) End Function - Public Async Function WhenUsingAddAssiginmentExpandsOperationProperly() As Task Const source = " @@ -399,7 +395,6 @@ Public Class MyType End If End Sub End Class" - Const fix = " Public Class MyType Public Sub Foo() @@ -407,9 +402,7 @@ Public Class MyType x = If(True, 1, x + 1) End Sub End Class" - - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + Await VerifyBasicFixAsync(source, fix) End Function @@ -425,7 +418,6 @@ Public Class MyType End If End Sub End Class" - Const fix = " Public Class MyType Public Sub Foo() @@ -433,25 +425,68 @@ Public Class MyType x = If(True, 1, x - 1) End Sub End Class" + Await VerifyBasicFixAsync(source, fix) + End Function - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + + Public Async Function WhenUsingConcatenationAssignmentOnElseAssignWithPlusExpandsToConcatenateAtEndOfTernary() As Task + Const source = " +Public Class MyType + Public Sub Foo() + Dim x = ""test"" + If True Then + x = ""1"" + Else + x += ""2"" + End If + End Sub +End Class" + Const fix = " +Public Class MyType + Public Sub Foo() + Dim x = ""test"" + x = If(True, ""1"", x + ""2"") + End Sub +End Class" + Await VerifyBasicFixAsync(source, fix) End Function - Public Async Function WhenUsingConcatenationAssignmentOnIfAssignExpandsToConcatenateAtEndOfTernary() As Task + Public Async Function WhenUsingConcatenationAssignmentOnIfAssignWithPlusExpandsToConcatenateAtEndOfTernary() As Task Const source = " Public Class MyType Public Sub Foo() Dim x = ""test"" If True Then - x &= ""1"" + x += ""1"" Else x = ""2"" End If End Sub End Class" + Const fix = " +Public Class MyType + Public Sub Foo() + Dim x = ""test"" + x = If(True, x + ""1"", ""2"") + End Sub +End Class" + Await VerifyBasicFixAsync(source, fix) + End Function + + Public Async Function WhenUsingConcatenationAssignmentOnIfAssignWithAmpersandExpandsToConcatenateAtEndOfTernary() As Task + Const source = " +Public Class MyType + Public Sub Foo() + Dim x = ""test"" + If True Then + x &= ""1"" + Else + x = ""2"" + End If + End Sub +End Class" Const fix = " Public Class MyType Public Sub Foo() @@ -459,9 +494,7 @@ Public Class MyType x = If(True, x & ""1"", ""2"") End Sub End Class" - - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + Await VerifyBasicFixAsync(source, fix) End Function @@ -477,7 +510,6 @@ Public Class MyType End If End Sub End Class" - Const fix = " Public Class MyType Public Sub Foo() @@ -485,13 +517,11 @@ Public Class MyType x = If(True, x + 1, 1) End Sub End Class" - - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + Await VerifyBasicFixAsync(source, fix) End Function - Public Async Function WhenUsingSubtractAssiginmentOnIfAssignExpandsOperationProperly() As Task + Public Async Function WhenUsingSubtractAssignmentOnIfAssignExpandsOperationProperly() As Task Const source = " Public Class MyType Public Sub Foo() @@ -503,7 +533,6 @@ Public Class MyType End If End Sub End Class" - Const fix = " Public Class MyType Public Sub Foo() @@ -511,9 +540,7 @@ Public Class MyType x = If(True, x - 1, 1) End Sub End Class" - - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + Await VerifyBasicFixAsync(source, fix) End Function @@ -566,9 +593,7 @@ Public Class MyType x = If(True, x + 1, x - 1) End Sub End Class" - - ' Allowing new diagnostics because without it the test fails because the compiler says Integer? is not defined. - Await VerifyBasicFixAsync(source, fix, allowNewCompilerDiagnostics:=True) + Await VerifyBasicFixAsync(source, fix) End Function End Class From 25b0270b2a54edaed4060365b67e37f8ecfb9c2c Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Mon, 26 Sep 2016 19:05:39 -0300 Subject: [PATCH 082/234] Fix #841 --- .../Refactoring/ComputeExpressionCodeFixProvider.cs | 8 ++++++-- .../Refactoring/ComputeExpressionTests.cs | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Refactoring/ComputeExpressionCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ComputeExpressionCodeFixProvider.cs index bf7e40551..cdfd8a563 100644 --- a/src/CSharp/CodeCracker/Refactoring/ComputeExpressionCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/ComputeExpressionCodeFixProvider.cs @@ -36,7 +36,7 @@ private async static Task ComputeExpressionAsync(Document document, Lo var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(diagnosticLocation.SourceSpan); var parenthesized = node as ParenthesizedExpressionSyntax; - var expression = (BinaryExpressionSyntax)(parenthesized != null ? parenthesized.Expression : node); + var expression = (BinaryExpressionSyntax)(parenthesized != null ? parenthesized.Expression : node is ArgumentSyntax ? ((ArgumentSyntax)node).Expression : node); var newRoot = ComputeExpression(node, expression, root, semanticModel); if (newRoot == null) return null; var newDocument = document.WithSyntaxRoot(newRoot); @@ -47,7 +47,11 @@ internal static SyntaxNode ComputeExpression(SyntaxNode nodeToReplace, BinaryExp { var result = semanticModel.GetConstantValue(expression); if (!result.HasValue) return null; - var newExpression = SyntaxFactory.ParseExpression(System.Convert.ToString(result.Value, System.Globalization.CultureInfo.InvariantCulture)); + SyntaxNode newExpression = SyntaxFactory.ParseExpression(System.Convert.ToString(result.Value, System.Globalization.CultureInfo.InvariantCulture)); + if(nodeToReplace is ArgumentSyntax) + { + newExpression = SyntaxFactory.Argument((ExpressionSyntax)newExpression); + } var newRoot = root.ReplaceNode(nodeToReplace, newExpression); return newRoot; } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs index 4b92b70be..e7a40762e 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs @@ -80,5 +80,13 @@ public async Task CompilerErrorDoesNotRegisterAFix() => [Fact] public async Task ExpressionThatThrowsDoesNotRegisterAFix() => await VerifyCSharpHasNoFixAsync("var a = int.MaxValue + int.MaxValue;".WrapInCSharpMethod()); + + [Fact] + public async Task ExpressionOnArgumentsFix() + { + var source = "string.Format(\"2 Hours in minutes: {0}\", 60 * 2)".WrapInCSharpMethod(); + var fix = "string.Format(\"2 Hours in minutes: {0}\", 120)".WrapInCSharpMethod(); + await VerifyCSharpFixAsync(source, fix); + } } } \ No newline at end of file From 37bfbfac79a118c8c005090cc730bece941d16dc Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 8 Jan 2017 21:31:44 -0200 Subject: [PATCH 083/234] Fix MakeReadonly with lambdas when field has initializer Fixes #853 Related to #544 but in that issue the variable was not initialized --- .../Usage/ReadonlyFieldAnalyzer.cs | 15 ++++++----- .../Usage/ReadonlyFieldTests.cs | 25 ++++++++++++++++++- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index d9db192ba..4ba9688b5 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -118,25 +118,28 @@ private static void VerifyVariable(Dictionary variablesToMakeReadonly, IFieldSymbol fieldSymbol, SyntaxNode assignment, SemanticModel semanticModel) + private static bool HasAssignmentInLambda(SyntaxNode assignment) { var parent = assignment.Parent; while (parent != null) { if (parent is AnonymousFunctionExpressionSyntax) - return; - if (parent is ConstructorDeclarationSyntax) - break; + return true; parent = parent.Parent; } + return false; + } + private static void AddVariableThatWasSkippedBeforeBecauseItLackedAInitializer(Dictionary variablesToMakeReadonly, IFieldSymbol fieldSymbol, SyntaxNode assignment, SemanticModel semanticModel) + { if (!fieldSymbol.IsReadOnly && !variablesToMakeReadonly.Keys.Contains(fieldSymbol)) { var containingType = assignment.FirstAncestorOfKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration); diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index e4181d876..25442201e 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -849,6 +849,29 @@ public Test() await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task FieldsAssignedOnLambdaWithInitializerDoesNotCreateDiagnostic() + { + const string source = @" +using System; +class C +{ + private readonly Action set; + private int i = 0; + + public C() + { + set = () => i = 1; + } + + public void Modify() + { + set(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task VariableInitializerDoesNotCreateDiagnostic() { @@ -992,4 +1015,4 @@ public Test() await VerifyCSharpHasNoDiagnosticsAsync(source); } } -} +} \ No newline at end of file From af791db541fd98e7a0bbb7121967789d9e57cd4c Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Mon, 9 Jan 2017 00:18:01 -0200 Subject: [PATCH 084/234] Remove async from DisposablesShouldCallSuppressFinalizeAnalyzer Fixes #821 --- .../Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.vb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.vb b/src/VisualBasic/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.vb index c7ee0b6e2..2b80fa72d 100644 --- a/src/VisualBasic/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Usage/DisposablesShouldCallSuppressFinalizeAnalyzer.vb @@ -35,7 +35,7 @@ This rule should be followed even if the class doesn't have a finalizer in a der context.RegisterSymbolAction(AddressOf AnalyzeAsync, SymbolKind.NamedType) End Sub - Public Async Sub AnalyzeAsync(context As SymbolAnalysisContext) + Public Sub AnalyzeAsync(context As SymbolAnalysisContext) If (context.IsGenerated()) Then Return Dim symbol = DirectCast(context.Symbol, INamedTypeSymbol) If symbol.TypeKind <> TypeKind.Class Then Exit Sub @@ -48,7 +48,7 @@ This rule should be followed even if the class doesn't have a finalizer in a der Dim disposeMethod = FindDisposeMethod(symbol) If disposeMethod Is Nothing Then Exit Sub - Dim syntaxTree = Await disposeMethod.DeclaringSyntaxReferences(0)?.GetSyntaxAsync(context.CancellationToken) + Dim syntaxTree = disposeMethod.DeclaringSyntaxReferences(0)?.GetSyntax(context.CancellationToken) Dim methodBlock = TryCast(TryCast(syntaxTree, MethodStatementSyntax)?.Parent, MethodBlockSyntax) Dim statements = methodBlock?.Statements.OfType(Of ExpressionStatementSyntax) From e0492cf1f941c552ed04b93c10875745fc567968 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Mon, 9 Jan 2017 00:25:21 -0200 Subject: [PATCH 085/234] Fix grammar in MakeLocalVariableConstWhenItIsPossibleAnalyzer And on the test Fixes #838 Related to #839 --- .../MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs | 2 +- .../MakeLocalVariablesConstWhenItIsPossibleTests.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs index 60dc5f397..f49aba20a 100644 --- a/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/MakeLocalVariableConstWhenItIsPossibleAnalyzer.cs @@ -12,7 +12,7 @@ public class MakeLocalVariableConstWhenItIsPossibleAnalyzer : DiagnosticAnalyzer { internal const string Title = "Make Local Variable Constant."; - internal const string MessageFormat = "This variables can be made const."; + internal const string MessageFormat = "This variable can be made const."; internal const string Category = SupportedCategories.Performance; const string Description = "This variable is assigned a constant value and never changed it can be made 'const'"; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( diff --git a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs index 3bbd8e378..e37f52a46 100644 --- a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs @@ -67,7 +67,7 @@ public async Task CreateDiagnosticsWhenAssigningAPotentialConstant() var expected = new DiagnosticResult { Id = DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), - Message = "This variables can be made const.", + Message = "This variable can be made const.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } }; @@ -82,7 +82,7 @@ public async Task CreateDiagnosticsWhenAssigningAPotentialConstantInAVarDeclarat var expected = new DiagnosticResult { Id = DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), - Message = "This variables can be made const.", + Message = "This variable can be made const.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } }; @@ -97,7 +97,7 @@ public async Task CreateDiagnosticsWhenAssigningNullToAReferenceType() var expected = new DiagnosticResult { Id = DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), - Message = "This variables can be made const.", + Message = "This variable can be made const.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } }; From e071c8ad8392d6c007d7fbaf1056b89cb6343a33 Mon Sep 17 00:00:00 2001 From: Hubert Kindermann Date: Fri, 13 Jan 2017 11:36:57 +0100 Subject: [PATCH 086/234] Fixes #854. --- .../Usage/ReadonlyFieldAnalyzer.cs | 8 +++--- .../Usage/ReadonlyFieldTests.cs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index d9db192ba..6ee2c84e1 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -2,9 +2,9 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Collections.Generic; namespace CodeCracker.CSharp.Usage { @@ -137,7 +137,7 @@ private static void AddVariableThatWasSkippedBeforeBecauseItLackedAInitializer(D parent = parent.Parent; } - if (!fieldSymbol.IsReadOnly && !variablesToMakeReadonly.Keys.Contains(fieldSymbol)) + if (!fieldSymbol.IsReadOnly && !variablesToMakeReadonly.Keys.Contains(fieldSymbol) && !IsComplexValueType(fieldSymbol.Type)) { var containingType = assignment.FirstAncestorOfKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration); if (containingType == null) return; @@ -196,9 +196,11 @@ private static bool IsComplexValueType(SemanticModel semanticModel, FieldDeclara { var fieldTypeName = fieldDeclaration.Declaration.Type; var fieldType = semanticModel.GetTypeInfo(fieldTypeName).ConvertedType; - return fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + return IsComplexValueType(fieldType); } + private static bool IsComplexValueType(ITypeSymbol fieldType) => fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + private static bool CanBeMadeReadonly(IFieldSymbol fieldSymbol) { return (fieldSymbol.DeclaredAccessibility == Accessibility.NotApplicable diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index e4181d876..fb208a531 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -988,6 +988,32 @@ public Test() { value = 8; } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task ComplexTypeDoesNotCreateDiagnosticAsync() + { + const string source = @" +class C +{ + private S s; + + public C() + { + s = default(S); + } + + public void M1() + { + s.Value = 1; + } + + public struct S + { + public int Value; + } }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } From 50ea8e08577c4df93702814cb9722484bf0d010a Mon Sep 17 00:00:00 2001 From: Hubert Kindermann Date: Mon, 16 Jan 2017 13:07:18 +0100 Subject: [PATCH 087/234] Fix #CC0060. --- ...ctClassShouldNotHavePublicCtorsAnalyzer.cs | 8 +++---- ...stractClassShouldNotHavePublicCtorTests.cs | 24 +++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs b/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs index 4e70142cd..f753cbebe 100644 --- a/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs @@ -1,9 +1,9 @@ -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; +using System.Collections.Immutable; +using System.Linq; namespace CodeCracker.CSharp.Usage { @@ -33,7 +33,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var ctor = (ConstructorDeclarationSyntax)context.Node; if (!ctor.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword))) return; - var @class = ctor.Ancestors().OfType().FirstOrDefault(); + var @class = ctor.Ancestors().FirstOrDefault() as ClassDeclarationSyntax; if (@class == null) return; if (!@class.Modifiers.Any(m => m.IsKind(SyntaxKind.AbstractKeyword))) return; diff --git a/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs b/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs index 6d804ca61..4fd659794 100644 --- a/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs @@ -1,6 +1,6 @@ -using System.Threading.Tasks; -using CodeCracker.CSharp.Usage; +using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using System.Threading.Tasks; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -66,6 +66,26 @@ private Foo() { /* .. */ } await VerifyCSharpHasNoDiagnosticsAsync(test); } + [Fact] + public async Task IgnoresCtorOfStructNestedInAbstractClasses() + { + const string test = @" + public abstract class C + { + public struct S + { + private int x; + + public S(int x) + { + this.x = x; + } + } + }"; + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + [Fact] public async Task FixReplacesPublicWithProtectedModifierInAbstractClasses() { From 8a8dc0ee8221f76aca22b871411a97560442ca7a Mon Sep 17 00:00:00 2001 From: Hubert Kindermann Date: Mon, 16 Jan 2017 13:16:27 +0100 Subject: [PATCH 088/234] Revert "Fix #CC0060." This reverts commit 50ea8e08577c4df93702814cb9722484bf0d010a. --- ...ctClassShouldNotHavePublicCtorsAnalyzer.cs | 8 +++---- ...stractClassShouldNotHavePublicCtorTests.cs | 24 ++----------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs b/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs index f753cbebe..4e70142cd 100644 --- a/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Immutable; -using System.Linq; namespace CodeCracker.CSharp.Usage { @@ -33,7 +33,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var ctor = (ConstructorDeclarationSyntax)context.Node; if (!ctor.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword))) return; - var @class = ctor.Ancestors().FirstOrDefault() as ClassDeclarationSyntax; + var @class = ctor.Ancestors().OfType().FirstOrDefault(); if (@class == null) return; if (!@class.Modifiers.Any(m => m.IsKind(SyntaxKind.AbstractKeyword))) return; diff --git a/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs b/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs index 4fd659794..6d804ca61 100644 --- a/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs @@ -1,6 +1,6 @@ -using CodeCracker.CSharp.Usage; +using System.Threading.Tasks; +using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; -using System.Threading.Tasks; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -66,26 +66,6 @@ private Foo() { /* .. */ } await VerifyCSharpHasNoDiagnosticsAsync(test); } - [Fact] - public async Task IgnoresCtorOfStructNestedInAbstractClasses() - { - const string test = @" - public abstract class C - { - public struct S - { - private int x; - - public S(int x) - { - this.x = x; - } - } - }"; - - await VerifyCSharpHasNoDiagnosticsAsync(test); - } - [Fact] public async Task FixReplacesPublicWithProtectedModifierInAbstractClasses() { From 20bd8a042b47e8b7523d47c3e04673b086c9c7a6 Mon Sep 17 00:00:00 2001 From: Stefan Theiner Date: Mon, 6 Feb 2017 09:25:34 +0100 Subject: [PATCH 089/234] Fix #872: UnusedParametersAnalyzer Analyzer should not be triggered on virtual methods Includes test case and fix. --- .../Usage/UnusedParametersAnalyzer.cs | 6 ++++++ .../Usage/UnusedParametersTests.cs | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs index cec3e43ea..cae19517e 100644 --- a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs @@ -59,6 +59,12 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) } var method = methodOrConstructor as MethodDeclarationSyntax; + + // It is legit for virtual methods to have parameters that aren't used in the default + // base class implementation, but are only provided for sub classes instead. + // See https://github.com/code-cracker/code-cracker/issues/872 + if (method?.Modifiers.Any(SyntaxKind.VirtualKeyword) == true) return; + IEnumerable methodChildren = methodOrConstructor.Body?.Statements; var expressionBody = (methodOrConstructor as MethodDeclarationSyntax)?.ExpressionBody; if (methodChildren == null && expressionBody != null) diff --git a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs index 44cf5f2b9..2b08add48 100644 --- a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs @@ -893,5 +893,24 @@ public class TypeName }"; await VerifyCSharpFixAsync(source, fixtest); } + + /// + /// Virtual methods should be ignored by the analyzer, because variables don't need + /// to be actually used by the base class and still serve a legit purpose. + /// + [Fact] + public async Task VirtualMethodsShouldBeIgnored() + { + + const string source = @" +public class BaseClass +{ + protected virtual void PreProcess(string data) + { + // no real action in base class + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From a9df7f4496941157c90aeafd57fd16a2becb5487 Mon Sep 17 00:00:00 2001 From: sdygert Date: Mon, 20 Feb 2017 20:31:51 -0800 Subject: [PATCH 090/234] Fixed grammer in CatchEmptyAnalyzer --- src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs | 6 +++--- src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs b/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs index ca0c5506a..82e455d7f 100644 --- a/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs @@ -10,7 +10,7 @@ namespace CodeCracker.CSharp.Design [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CatchEmptyAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Your catch maybe include some Exception"; + internal const string Title = "Your catch should include an Exception"; internal const string MessageFormat = "{0}"; internal const string Category = SupportedCategories.Design; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( @@ -33,7 +33,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) var catchStatement = (CatchClauseSyntax)context.Node; if (catchStatement == null || catchStatement.Declaration != null) return; - if (catchStatement.Block?.Statements.Count == 0) return; // there is another analizer for this: EmptyCatchBlock + if (catchStatement.Block?.Statements.Count == 0) return; // there is another analyzer for this: EmptyCatchBlock if (catchStatement.Block != null) { @@ -42,7 +42,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (!controlFlow.EndPointIsReachable && controlFlow.ExitPoints.All(i => i.IsKind(SyntaxKind.ThrowStatement))) return; } - var diagnostic = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider put an Exception Class in catch."); + var diagnostic = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider adding an Exception to the catch."); context.ReportDiagnostic(diagnostic); } } diff --git a/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb b/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb index 132345083..e4f1b7c9c 100644 --- a/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb @@ -9,7 +9,7 @@ Namespace Design Inherits DiagnosticAnalyzer Public Shared ReadOnly Id As String = DiagnosticId.CatchEmpty.ToDiagnosticId() - Public Const Title As String = "Your catch may includes some Exception" + Public Const Title As String = "Your catch should include an Exception" Public Const MessageFormat As String = "{0}" Public Const Category As String = SupportedCategories.Design Protected Shared Rule As DiagnosticDescriptor = New DiagnosticDescriptor( @@ -33,7 +33,7 @@ Namespace Design If catchStatement Is Nothing Then Exit Sub If catchStatement.IdentifierName Is Nothing Then - Dim diag = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider including an Exception Class in catch.") + Dim diag = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider adding an Exception to the catch.") context.ReportDiagnostic(diag) End If End Sub From e4d2a3152a8fb20ca0ccac48a58e3f388ca89a16 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Mon, 27 Feb 2017 19:17:58 +0100 Subject: [PATCH 091/234] #522 first prototype --- .../Style/TernaryOperatorCodeFixProvider.cs | 69 +++++++++- .../Style/TernaryOperatorTests.cs | 123 ++++++++++++++++++ 2 files changed, 185 insertions(+), 7 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 97ebd2e3f..0e6a22ed6 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System; namespace CodeCracker.CSharp.Style { @@ -37,11 +38,10 @@ private static async Task MakeTernaryAsync(Document document, Diagnost var elseStatement = ifStatement.Else; var returnStatementInsideElse = (ReturnStatementSyntax)(elseStatement.Statement is BlockSyntax ? ((BlockSyntax)elseStatement.Statement).Statements.Single() : elseStatement.Statement); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - ExpressionSyntax trueExpression, falseExpression; - TernaryOperatorCodeFixHelper.CreateExpressions(returnStatementInsideIf.Expression, returnStatementInsideElse.Expression, semanticModel, out trueExpression, out falseExpression); + var conditionalExpression = TernaryOperatorCodeFixHelper.CreateExpressions(returnStatementInsideIf.Expression, returnStatementInsideElse.Expression, ifStatement.Condition, semanticModel); var ternary = SyntaxFactory.ReturnStatement( - SyntaxFactory.ConditionalExpression(ifStatement.Condition, trueExpression, falseExpression)) + conditionalExpression) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); @@ -76,14 +76,13 @@ private static async Task MakeTernaryAsync(Document document, Diagnost var assignmentExpressionInsideIf = (AssignmentExpressionSyntax)expressionInsideIf.Expression; var assignmentExpressionInsideElse = (AssignmentExpressionSyntax)expressionInsideElse.Expression; var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - ExpressionSyntax trueExpression, falseExpression; - TernaryOperatorCodeFixHelper.CreateExpressions(assignmentExpressionInsideIf.Right, assignmentExpressionInsideElse.Right, semanticModel, out trueExpression, out falseExpression); + var conditionalExpression = TernaryOperatorCodeFixHelper.CreateExpressions(assignmentExpressionInsideIf.Right, assignmentExpressionInsideElse.Right, ifStatement.Condition, semanticModel); var ternary = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( assignmentExpressionInsideIf.Kind(), assignmentExpressionInsideIf.Left, - SyntaxFactory.ConditionalExpression(ifStatement.Condition, trueExpression, falseExpression))) + conditionalExpression)) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); @@ -95,13 +94,69 @@ private static async Task MakeTernaryAsync(Document document, Diagnost internal static class TernaryOperatorCodeFixHelper { - public static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel, out ExpressionSyntax trueExpression, out ExpressionSyntax falseExpression) + public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, ExpressionSyntax ifStatementCondition, SemanticModel semanticModel) + { + + var methodCallSimplification = TrySimplifyMethodCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (methodCallSimplification != null) return methodCallSimplification; + var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); + var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); + var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); + ExpressionSyntax trueExpression; ExpressionSyntax falseExpression; + CreateExpressions(ifExpression, elseExpression, ifTypeInfo.Type, elseTypeInfo.Type, + ifTypeInfo.ConvertedType, elseTypeInfo.ConvertedType, typeSyntax, semanticModel, out trueExpression, out falseExpression); + return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); + } + + private static ExpressionSyntax TrySimplifyMethodCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + { + if (ifExpression is InvocationExpressionSyntax && elseExpression is InvocationExpressionSyntax) + { + var ifInvocation = ifExpression as InvocationExpressionSyntax; + var elseInvocation = elseExpression as InvocationExpressionSyntax; + var ifMethodinfo = semanticModel.GetSymbolInfo(ifInvocation.Expression); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation.Expression); + if (object.Equals(ifMethodinfo, elseMethodinfo)) //same method and overload + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.InvocationExpression(ifInvocation.Expression, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel)); + } + } + return null; + } + + private static ArgumentListSyntax CreateMethodArgumentList(ExpressionSyntax ifStatementCondition, ArgumentListSyntax argList1, ArgumentListSyntax argList2, int argumentIndexThatDiffers, SemanticModel semanticModel) + { + var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); + var argSelector = zipped.Select((args, i) => + (i == argumentIndexThatDiffers) ? + SyntaxFactory.Argument(GetConditionalExpressionForArgument(ifStatementCondition, args.a1.Expression, args.a2.Expression, semanticModel)) + : args.a1); + return SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argSelector)); + } + + private static ConditionalExpressionSyntax GetConditionalExpressionForArgument(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) { var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); + ExpressionSyntax trueExpression; ExpressionSyntax falseExpression; CreateExpressions(ifExpression, elseExpression, ifTypeInfo.Type, elseTypeInfo.Type, ifTypeInfo.ConvertedType, elseTypeInfo.ConvertedType, typeSyntax, semanticModel, out trueExpression, out falseExpression); + return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); + } + + private static int FindSingleArgumentIndexThatDiffers(ArgumentListSyntax argList1, ArgumentListSyntax argList2, SemanticModel semanticModel) + { + var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); + var singleMissmatch = zipped.Where(args => + { + var a1Text = args.a1.GetText(); + var a2Text = args.a2.GetText(); + return !a1Text.ContentEquals(a2Text); + }).Take(2).ToList(); + return (singleMissmatch.Count == 0 || singleMissmatch.Count > 1) ? -1 : singleMissmatch[0].i; } private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 68d90f96d..fcd61b6a1 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -723,5 +723,128 @@ public static Base Foo() "; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenReturnStatementContainsMethodCallAnalyzerCreatesDiagnostic() + { + var source = @" + private int Method(int i) => i; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), + Message = "You can use a ternary operator.", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 17) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithSingleDifferentArgumentGetsSimplified() + { + var source = @" + private int Method(int i) => i; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i) => i; + + public int Foo() + { + return Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereSingleDifferentGetsSimplified() + { + var source = @" + private int Method(int i, string t) => i; + + public int Foo() + { + if (true) + return Method(1, ""hello""); + else + return Method(2, ""hello""); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i, string t) => i; + + public int Foo() + { + return Method(true?1:2, ""hello""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereMultipleDifferentGetsNotSimplified() + { + var source = @" + private int Method(int i, string t) => i; + + public int Foo() + { + if (true) + return Method(1, ""hello1""); + else + return Method(2, ""hello2""); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i, string t) => i; + + public int Foo() + { + return true?Method(1,""hello1""):Method(2, ""hello2""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodArgumentsGetCastedWhenSimplified() + { + var source = @" + class Base { } + class A : Base { } + class B : Base { } + + private string Method(Base b, string t) => t; + + public int Foo() + { + if (true) + return Method(new A(), ""hello""); + else + return Method(new B(), ""hello""); + }".WrapInCSharpClass(); + var fixtest = @" + class Base { } + class A : Base { } + class B : Base { } + + private string Method(Base b, string t) => t; + + public int Foo() + { + return Method(true?(Base)new A():new B(),""hello""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From 0b218c0ffa0107b21c7a24b3e32805de112e82f6 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Tue, 28 Feb 2017 18:55:27 +0100 Subject: [PATCH 092/234] Small improvement and many more tests --- .../Style/TernaryOperatorCodeFixProvider.cs | 11 +- .../Style/TernaryOperatorTests.cs | 230 +++++++++++++++++- 2 files changed, 235 insertions(+), 6 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 0e6a22ed6..33a44e884 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -118,9 +118,12 @@ private static ExpressionSyntax TrySimplifyMethodCalls(ExpressionSyntax ifStatem var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation.Expression); if (object.Equals(ifMethodinfo, elseMethodinfo)) //same method and overload { - var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); - if (findSingleArgumentIndexThatDiffers >= 0) - return SyntaxFactory.InvocationExpression(ifInvocation.Expression, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel)); + if (ifInvocation.Expression.GetText().ContentEquals(elseInvocation.Expression.GetText())) //same 'path' to the invocation + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.InvocationExpression(ifInvocation.Expression, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel)); + } } } return null; @@ -156,7 +159,7 @@ private static int FindSingleArgumentIndexThatDiffers(ArgumentListSyntax argList var a2Text = args.a2.GetText(); return !a1Text.ContentEquals(a2Text); }).Take(2).ToList(); - return (singleMissmatch.Count == 0 || singleMissmatch.Count > 1) ? -1 : singleMissmatch[0].i; + return (singleMissmatch.Count == 1) ? singleMissmatch[0].i : -1; } private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index fcd61b6a1..0300d66b0 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -334,6 +334,68 @@ public static void Foo() "; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultChangeToTernaryFixGetsSimplified() + { + var source = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + if (something) + { + a = Method(1); + } + else + { + a = Method(2); + } + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + a = Method(something?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultWithComplexArgumentEvaluationChangeToTernaryFixGetsSimplified() + { + var source = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + if (something) + { + a = Method(1); + } + else + { + a = Method(2 + 2); + } + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + a = Method(something?1:2 + 2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } public class TernaryOperatorWithReturnTests : CodeFixVerifier @@ -824,7 +886,7 @@ class Base { } class A : Base { } class B : Base { } - private string Method(Base b, string t) => t; + private int Method(Base b, string t) => 1; public int Foo() { @@ -838,7 +900,7 @@ class Base { } class A : Base { } class B : Base { } - private string Method(Base b, string t) => t; + private int Method(Base b, string t) => 1; public int Foo() { @@ -846,5 +908,169 @@ public int Foo() }".WrapInCSharpClass(); await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task FixWhenReturningWithPrefixedMethodGetsSimplified() + { + var source = @" + private int Method(int a) => a; + + public int Foo() + { + if (true) + return this.Method(1); + else + return this.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int a) => a; + + public int Foo() + { + return this.Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfPropertyGetsSimplified() + { + var source = @" + class A { + private int Method(int a) => a; + } + + public int Foo() + { + var a=new A(); + if (true) + return a.Method(1); + else + return a.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + class A { + private int Method(int a) => a; + } + + public int Foo() + { + var a=new A(); + return a.Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentPropertyGetsNotSimplified() + { + var source = @" + class A { + public int Method(int a) => a; + } + A Prop1 { get { return new A(); } } + A Prop2 { get { return new A(); } } + + public int Foo() + { + if (true) + return this.Prop1.Method(1); + else + return this.Prop2.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + class A { + public int Method(int a) => a; + } + A Prop1 { get { return new A(); } } + A Prop2 { get { return new A(); } } + + public int Foo() + { + return true?this.Prop1.Method(1):this.Prop2.Method(2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfSameOverloadGetsSimplified() + { + var source = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + return Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentOverloadGetsNotSimplified() + { + var source = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(""2""); + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + return true?Method(1):Method(""2""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodNestedInMemberAccessGetsNotSimplified() + { + var source = @" + class A { + public int Prop { get; } + } + + A GetA(int i) => new A(); + + public int Foo() + { + if (true) + return GetA(1).Prop; + else + return GetA(2).Prop; + }".WrapInCSharpClass(); + var fixtest = @" + class A { + public int Prop { get; } + } + + A GetA(int i) => new A(); + + public int Foo() + { + return true?GetA(1).Prop:GetA(2).Prop; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From e3b934f0cf68c7f433cdfcc32893a5953c6a074a Mon Sep 17 00:00:00 2001 From: Stefan Theiner Date: Mon, 6 Feb 2017 09:25:34 +0100 Subject: [PATCH 093/234] Fix #872: UnusedParametersAnalyzer Analyzer should not be triggered on virtual methods Includes test case and fix. --- .../Usage/UnusedParametersAnalyzer.cs | 6 ++++++ .../Usage/UnusedParametersTests.cs | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs index cec3e43ea..cae19517e 100644 --- a/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/UnusedParametersAnalyzer.cs @@ -59,6 +59,12 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) } var method = methodOrConstructor as MethodDeclarationSyntax; + + // It is legit for virtual methods to have parameters that aren't used in the default + // base class implementation, but are only provided for sub classes instead. + // See https://github.com/code-cracker/code-cracker/issues/872 + if (method?.Modifiers.Any(SyntaxKind.VirtualKeyword) == true) return; + IEnumerable methodChildren = methodOrConstructor.Body?.Statements; var expressionBody = (methodOrConstructor as MethodDeclarationSyntax)?.ExpressionBody; if (methodChildren == null && expressionBody != null) diff --git a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs index 44cf5f2b9..2b08add48 100644 --- a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs @@ -893,5 +893,24 @@ public class TypeName }"; await VerifyCSharpFixAsync(source, fixtest); } + + /// + /// Virtual methods should be ignored by the analyzer, because variables don't need + /// to be actually used by the base class and still serve a legit purpose. + /// + [Fact] + public async Task VirtualMethodsShouldBeIgnored() + { + + const string source = @" +public class BaseClass +{ + protected virtual void PreProcess(string data) + { + // no real action in base class + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } } \ No newline at end of file From b5fe3e6542764e8be365920726b4e5130b62d99b Mon Sep 17 00:00:00 2001 From: sdygert Date: Mon, 20 Feb 2017 20:31:51 -0800 Subject: [PATCH 094/234] Fixed grammer in CatchEmptyAnalyzer --- src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs | 6 +++--- src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs b/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs index ca0c5506a..82e455d7f 100644 --- a/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/CatchEmptyAnalyzer.cs @@ -10,7 +10,7 @@ namespace CodeCracker.CSharp.Design [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CatchEmptyAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Your catch maybe include some Exception"; + internal const string Title = "Your catch should include an Exception"; internal const string MessageFormat = "{0}"; internal const string Category = SupportedCategories.Design; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( @@ -33,7 +33,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) var catchStatement = (CatchClauseSyntax)context.Node; if (catchStatement == null || catchStatement.Declaration != null) return; - if (catchStatement.Block?.Statements.Count == 0) return; // there is another analizer for this: EmptyCatchBlock + if (catchStatement.Block?.Statements.Count == 0) return; // there is another analyzer for this: EmptyCatchBlock if (catchStatement.Block != null) { @@ -42,7 +42,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (!controlFlow.EndPointIsReachable && controlFlow.ExitPoints.All(i => i.IsKind(SyntaxKind.ThrowStatement))) return; } - var diagnostic = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider put an Exception Class in catch."); + var diagnostic = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider adding an Exception to the catch."); context.ReportDiagnostic(diagnostic); } } diff --git a/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb b/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb index 132345083..e4f1b7c9c 100644 --- a/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Design/CatchEmptyAnalyzer.vb @@ -9,7 +9,7 @@ Namespace Design Inherits DiagnosticAnalyzer Public Shared ReadOnly Id As String = DiagnosticId.CatchEmpty.ToDiagnosticId() - Public Const Title As String = "Your catch may includes some Exception" + Public Const Title As String = "Your catch should include an Exception" Public Const MessageFormat As String = "{0}" Public Const Category As String = SupportedCategories.Design Protected Shared Rule As DiagnosticDescriptor = New DiagnosticDescriptor( @@ -33,7 +33,7 @@ Namespace Design If catchStatement Is Nothing Then Exit Sub If catchStatement.IdentifierName Is Nothing Then - Dim diag = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider including an Exception Class in catch.") + Dim diag = Diagnostic.Create(Rule, catchStatement.GetLocation(), "Consider adding an Exception to the catch.") context.ReportDiagnostic(diag) End If End Sub From 233cdf7474110d48144c0fe9083e37eca292386b Mon Sep 17 00:00:00 2001 From: hkindermann Date: Mon, 16 Jan 2017 14:23:06 +0100 Subject: [PATCH 095/234] Fixes #867. --- ...ctClassShouldNotHavePublicCtorsAnalyzer.cs | 8 +++---- ...stractClassShouldNotHavePublicCtorTests.cs | 24 +++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs b/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs index 4e70142cd..f753cbebe 100644 --- a/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/AbstractClassShouldNotHavePublicCtorsAnalyzer.cs @@ -1,9 +1,9 @@ -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; +using System.Collections.Immutable; +using System.Linq; namespace CodeCracker.CSharp.Usage { @@ -33,7 +33,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var ctor = (ConstructorDeclarationSyntax)context.Node; if (!ctor.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword))) return; - var @class = ctor.Ancestors().OfType().FirstOrDefault(); + var @class = ctor.Ancestors().FirstOrDefault() as ClassDeclarationSyntax; if (@class == null) return; if (!@class.Modifiers.Any(m => m.IsKind(SyntaxKind.AbstractKeyword))) return; diff --git a/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs b/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs index 6d804ca61..4fd659794 100644 --- a/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/AbstractClassShouldNotHavePublicCtorTests.cs @@ -1,6 +1,6 @@ -using System.Threading.Tasks; -using CodeCracker.CSharp.Usage; +using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using System.Threading.Tasks; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -66,6 +66,26 @@ private Foo() { /* .. */ } await VerifyCSharpHasNoDiagnosticsAsync(test); } + [Fact] + public async Task IgnoresCtorOfStructNestedInAbstractClasses() + { + const string test = @" + public abstract class C + { + public struct S + { + private int x; + + public S(int x) + { + this.x = x; + } + } + }"; + + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + [Fact] public async Task FixReplacesPublicWithProtectedModifierInAbstractClasses() { From e86f1ffca13e8e561433f71b06ea945be3705d25 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 8 Mar 2017 14:32:30 +0100 Subject: [PATCH 096/234] Supoport for constructor calls added. --- .../Style/TernaryOperatorCodeFixProvider.cs | 20 +++++++++++++++++++ .../Style/TernaryOperatorTests.cs | 19 ++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 33a44e884..2f3b6a0c0 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -99,6 +99,8 @@ public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, var methodCallSimplification = TrySimplifyMethodCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); if (methodCallSimplification != null) return methodCallSimplification; + var constructorSimplification = TrySimplifyConstructorCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (constructorSimplification != null) return constructorSimplification; var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); @@ -108,6 +110,24 @@ public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); } + private static ExpressionSyntax TrySimplifyConstructorCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + { + if (ifExpression is ObjectCreationExpressionSyntax && elseExpression is ObjectCreationExpressionSyntax) + { + var ifInvocation = ifExpression as ObjectCreationExpressionSyntax; + var elseInvocation = elseExpression as ObjectCreationExpressionSyntax; + var ifMethodinfo = semanticModel.GetSymbolInfo(ifInvocation); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation); + if (object.Equals(ifMethodinfo, elseMethodinfo)) //same method and overload + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.ObjectCreationExpression(ifInvocation.Type, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel), null); + } + } + return null; + } + private static ExpressionSyntax TrySimplifyMethodCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) { if (ifExpression is InvocationExpressionSyntax && elseExpression is InvocationExpressionSyntax) diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 0300d66b0..714041c00 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -1072,5 +1072,24 @@ public int Foo() }".WrapInCSharpClass(); await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task FixWhenReturningWithConstructorGetsSimplified() + { + var source = @" + public int Foo() + { + if (true) + return new System.Collections.Generic.List(1); + else + return new System.Collections.Generic.List(2); + }".WrapInCSharpClass(); + var fixtest = @" + public int Foo() + { + return new System.Collections.Generic.List(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From 36eaae34115e5b0b63089e77935a1ea2833a7b8a Mon Sep 17 00:00:00 2001 From: Hubert Kindermann Date: Fri, 13 Jan 2017 11:36:57 +0100 Subject: [PATCH 097/234] Fixes #854. --- .../Usage/ReadonlyFieldAnalyzer.cs | 8 +++--- .../Usage/ReadonlyFieldTests.cs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index 4ba9688b5..1fa957957 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -2,9 +2,9 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Collections.Generic; namespace CodeCracker.CSharp.Usage { @@ -140,7 +140,7 @@ private static bool HasAssignmentInLambda(SyntaxNode assignment) private static void AddVariableThatWasSkippedBeforeBecauseItLackedAInitializer(Dictionary variablesToMakeReadonly, IFieldSymbol fieldSymbol, SyntaxNode assignment, SemanticModel semanticModel) { - if (!fieldSymbol.IsReadOnly && !variablesToMakeReadonly.Keys.Contains(fieldSymbol)) + if (!fieldSymbol.IsReadOnly && !variablesToMakeReadonly.Keys.Contains(fieldSymbol) && !IsComplexValueType(fieldSymbol.Type)) { var containingType = assignment.FirstAncestorOfKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration); if (containingType == null) return; @@ -199,9 +199,11 @@ private static bool IsComplexValueType(SemanticModel semanticModel, FieldDeclara { var fieldTypeName = fieldDeclaration.Declaration.Type; var fieldType = semanticModel.GetTypeInfo(fieldTypeName).ConvertedType; - return fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + return IsComplexValueType(fieldType); } + private static bool IsComplexValueType(ITypeSymbol fieldType) => fieldType.IsValueType && !(fieldType.TypeKind == TypeKind.Enum || fieldType.IsPrimitive()); + private static bool CanBeMadeReadonly(IFieldSymbol fieldSymbol) { return (fieldSymbol.DeclaredAccessibility == Accessibility.NotApplicable diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index 25442201e..e49637973 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -1011,6 +1011,32 @@ public Test() { value = 8; } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task ComplexTypeDoesNotCreateDiagnosticAsync() + { + const string source = @" +class C +{ + private S s; + + public C() + { + s = default(S); + } + + public void M1() + { + s.Value = 1; + } + + public struct S + { + public int Value; + } }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } From 7b21fbdd55ba90e2ccde1d3835ca698ef84660aa Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 11 Mar 2017 18:47:14 -0300 Subject: [PATCH 098/234] Migrate projects to VS2017 format and create new ones for VS2015 Anyone wanting to code on CodeCracker now should use VS2017, or use the new .2015.sln files --- CodeCracker.2015.sln | 141 ++++++++++++++++++ CodeCracker.CSharp.2015.sln | 101 +++++++++++++ CodeCracker.VisualBasic.2015.sln | 97 ++++++++++++ README.md | 5 + .../CodeCracker.Vsix.2015.csproj | 84 +++++++++++ .../CodeCracker.Vsix/CodeCracker.Vsix.csproj | 9 +- .../source.extension.vsixmanifest | 4 + .../CodeCracker.Vsix.2015.csproj | 84 +++++++++++ .../CodeCracker.Vsix/CodeCracker.Vsix.csproj | 7 +- 9 files changed, 529 insertions(+), 3 deletions(-) create mode 100644 CodeCracker.2015.sln create mode 100644 CodeCracker.CSharp.2015.sln create mode 100644 CodeCracker.VisualBasic.2015.sln create mode 100644 src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj create mode 100644 src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj diff --git a/CodeCracker.2015.sln b/CodeCracker.2015.sln new file mode 100644 index 000000000..729d7ca60 --- /dev/null +++ b/CodeCracker.2015.sln @@ -0,0 +1,141 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker", "src\CSharp\CodeCracker\CodeCracker.csproj", "{FF1097FB-A890-461B-979E-064697891B96}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{6BAC4057-7239-485E-A04B-02E687A83BAA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test", "test\CSharp\CodeCracker.Test\CodeCracker.Test.csproj", "{F7843158-046E-4B22-95D7-CAC7BB01283D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "vb", "vb", "{11473308-7FD9-43CE-84CE-5912EEFDD1DC}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cs", "cs", "{90D62FF0-A374-4C14-B827-1FFA8E384E18}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{B7B513B4-0317-4F32-B560-4BFC4FAEC239}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker.Test", "test\VisualBasic\CodeCracker.Test\CodeCracker.Test.vbproj", "{5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A26BEB5D-9C92-4F60-9789-563A327605C3}" + ProjectSection(SolutionItems) = preProject + src\CodeCracker.nuspec = src\CodeCracker.nuspec + nuget.config = nuget.config + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solution Items", "{E1B8ADBF-3442-4EF3-8C6B-146B576340E9}" + ProjectSection(SolutionItems) = preProject + .gitattributes = .gitattributes + .gitignore = .gitignore + CHANGELOG.md = CHANGELOG.md + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{234973E7-794D-4BC5-8D5F-FB98D8BFA967}" + ProjectSection(SolutionItems) = preProject + appveyor.yml = appveyor.yml + build.ps1 = build.ps1 + build.targets.ps1 = build.targets.ps1 + psake.ps1 = psake.ps1 + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6E93-4D2D-B6F0-141B977AFC9F}" + ProjectSection(SolutionItems) = preProject + test\CSharp\AnalyzeCecil.ps1 = test\CSharp\AnalyzeCecil.ps1 + test\CSharp\AnalyzeCoreFx.ps1 = test\CSharp\AnalyzeCoreFx.ps1 + test\CSharp\AnalyzeRoslyn.ps1 = test\CSharp\AnalyzeRoslyn.ps1 + runTestsCS.ps1 = runTestsCS.ps1 + runTestsVB.ps1 = runTestsVB.ps1 + test.ps1 = test.ps1 + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + DebugNoVsix|Any CPU = DebugNoVsix|Any CPU + Release|Any CPU = Release|Any CPU + ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.Build.0 = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.Build.0 = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.Build.0 = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {FF1097FB-A890-461B-979E-064697891B96} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} + {6BAC4057-7239-485E-A04B-02E687A83BAA} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} + {F7843158-046E-4B22-95D7-CAC7BB01283D} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} + {41FA4971-D354-4647-A269-4A886DA2EF4C} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} + {B7B513B4-0317-4F32-B560-4BFC4FAEC239} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} + {234973E7-794D-4BC5-8D5F-FB98D8BFA967} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} + {C5584F20-6E93-4D2D-B6F0-141B977AFC9F} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} + EndGlobalSection +EndGlobal diff --git a/CodeCracker.CSharp.2015.sln b/CodeCracker.CSharp.2015.sln new file mode 100644 index 000000000..0600d9a27 --- /dev/null +++ b/CodeCracker.CSharp.2015.sln @@ -0,0 +1,101 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F5240AD-2B4E-48A4-B9FC-7D19DACEF2CD}" + ProjectSection(SolutionItems) = preProject + nuget.config = nuget.config + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker", "src\CSharp\CodeCracker\CodeCracker.csproj", "{FF1097FB-A890-461B-979E-064697891B96}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.2015.Vsix", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{6BAC4057-7239-485E-A04B-02E687A83BAA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test", "test\CSharp\CodeCracker.Test\CodeCracker.Test.csproj", "{F7843158-046E-4B22-95D7-CAC7BB01283D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7B4F0131-D598-4692-9E2C-111E6C42C6AD}" + ProjectSection(SolutionItems) = preProject + .gitattributes = .gitattributes + .gitignore = .gitignore + CHANGELOG.md = CHANGELOG.md + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{051F1BE2-9A44-4B84-9DF8-6537852B7BBC}" + ProjectSection(SolutionItems) = preProject + test\CSharp\AnalyzeCecil.ps1 = test\CSharp\AnalyzeCecil.ps1 + test\CSharp\AnalyzeCoreFx.ps1 = test\CSharp\AnalyzeCoreFx.ps1 + test\CSharp\AnalyzeRoslyn.ps1 = test\CSharp\AnalyzeRoslyn.ps1 + runTestsCS.ps1 = runTestsCS.ps1 + test.ps1 = test.ps1 + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{40545653-8444-49E0-8DAD-BBB381F8A3B2}" + ProjectSection(SolutionItems) = preProject + appveyor.yml = appveyor.yml + build.ps1 = build.ps1 + build.targets.ps1 = build.targets.ps1 + psake.ps1 = psake.ps1 + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + DebugNoVsix|Any CPU = DebugNoVsix|Any CPU + Release|Any CPU = Release|Any CPU + ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.Build.0 = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU + {6BAC4057-7239-485E-A04B-02E687A83BAA}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.Build.0 = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {051F1BE2-9A44-4B84-9DF8-6537852B7BBC} = {7B4F0131-D598-4692-9E2C-111E6C42C6AD} + {40545653-8444-49E0-8DAD-BBB381F8A3B2} = {7B4F0131-D598-4692-9E2C-111E6C42C6AD} + EndGlobalSection +EndGlobal diff --git a/CodeCracker.VisualBasic.2015.sln b/CodeCracker.VisualBasic.2015.sln new file mode 100644 index 000000000..9d3b4ba56 --- /dev/null +++ b/CodeCracker.VisualBasic.2015.sln @@ -0,0 +1,97 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker.Test", "test\VisualBasic\CodeCracker.Test\CodeCracker.Test.vbproj", "{5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6}" + ProjectSection(SolutionItems) = preProject + .gitattributes = .gitattributes + .gitignore = .gitignore + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{5413BEBC-2F00-4B54-98E9-B1A7618C3C2A}" + ProjectSection(SolutionItems) = preProject + nuget.config = nuget.config + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D1591C8E-982D-402F-B3CB-1D1662104425}" + ProjectSection(SolutionItems) = preProject + appveyor.yml = appveyor.yml + build.ps1 = build.ps1 + build.targets.ps1 = build.targets.ps1 + psake.ps1 = psake.ps1 + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{22D6C608-E7F1-4236-BB07-BE5F97A4C810}" + ProjectSection(SolutionItems) = preProject + runTestsVB.ps1 = runTestsVB.ps1 + test.ps1 = test.ps1 + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{B7B513B4-0317-4F32-B560-4BFC4FAEC239}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + DebugNoVsix|Any CPU = DebugNoVsix|Any CPU + Release|Any CPU = Release|Any CPU + ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.Build.0 = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU + {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D1591C8E-982D-402F-B3CB-1D1662104425} = {3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6} + {22D6C608-E7F1-4236-BB07-BE5F97A4C810} = {3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md index f3ae91e29..6cfef52f6 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,11 @@ Then add a reference to CodeCracker.dll from within the Analyzers node inside Re ## Contributing +The main supported IDE for development is Visual Studio 2015. +If you want to use VS 2015 to contribute to Code Cracker use +the *.2015.sln files. We recommend migrating to VS 2017 ASAP, as +we might make VS 2015 obsolete at any time. + Questions, comments, bug reports, and pull requests are all welcome. Bug reports that include steps-to-reproduce (including code) are preferred. Even better, make them in the form of pull requests. diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj new file mode 100644 index 000000000..05f70110b --- /dev/null +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj @@ -0,0 +1,84 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {6BAC4057-7239-485E-A04B-02E687A83BAA} + Library + Properties + CodeCracker + CodeCracker.CSharp + v4.5.2 + false + false + false + false + false + false + Roslyn + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Program + $(DevEnvDir)devenv.exe + /rootsuffix Roslyn + + + + Designer + + + + + {FF1097FB-A890-461B-979E-064697891B96} + CodeCracker + + + + + Always + true + + + Always + true + + + Always + true + + + + + + \ No newline at end of file diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj index 05f70110b..12f744c47 100644 --- a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj @@ -1,9 +1,14 @@  - + - 14.0 + 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 15.0 diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index 96ab65b93..d2b7702fd 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -25,4 +25,8 @@ This is a community project, free and open source. Everyone is invited to contri + + + + diff --git a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj new file mode 100644 index 000000000..dcdad50cf --- /dev/null +++ b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj @@ -0,0 +1,84 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {B7B513B4-0317-4F32-B560-4BFC4FAEC239} + Library + Properties + CodeCracker + CodeCracker.VisualBasic + v4.5.2 + false + false + false + false + false + false + Roslyn + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Program + $(DevEnvDir)devenv.exe + /rootsuffix Roslyn + + + + Designer + + + + + Always + true + + + Always + true + + + Always + true + + + + + {41fa4971-d354-4647-a269-4a886da2ef4c} + CodeCracker + + + + + + \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.csproj b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.csproj index dcdad50cf..b2f8a0250 100644 --- a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.csproj +++ b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.csproj @@ -1,9 +1,14 @@  - 14.0 + 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 14.0 From f941c7b27342f856541398b056b27db4b37a516a Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 11 Mar 2017 18:58:29 -0300 Subject: [PATCH 099/234] Use VS 2017 on appveyor --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 58c443b5b..ac50d45ed 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,7 @@ version: 1.0.0.{build} +image: Visual Studio 2017 + configuration: ReleaseNoVsix init: @@ -17,8 +19,6 @@ environment: before_build: - ps: >- - $env:path="C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files (x86)\Microsoft SDKs\F#\4.0\Framework\v4.0\;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.1;C:\Program Files (x86)\MSBuild\14.0\bin;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\Microsoft.NET\Framework\v4.0.30319;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\VCPackages;C:\Program Files (x86)\HTML Help Workshop;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Performance Tools;C:\Program Files (x86)\Windows Kits\8.1\bin\x86;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.1\;$env:path" - . .\build.ps1 Prepare-Build From e42fce03c7669526314dc02b42fba5a9ca966b37 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 11 Mar 2017 19:38:06 -0300 Subject: [PATCH 100/234] Fix build.ps1 --- build.ps1 | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/build.ps1 b/build.ps1 index c51dd0bf9..691e90be6 100644 --- a/build.ps1 +++ b/build.ps1 @@ -16,21 +16,21 @@ function IsNugetVersion3($theNugetExe) { function Get-Nuget { if (gcm nuget -ErrorAction SilentlyContinue) { if (IsNugetVersion3 'nuget') { - return 'nuget' + $nugetExe = 'nuget' } else { Download-Nuget - return $localNuget + $nugetExe = $localNuget } } else { Download-Nuget - return $localNuget + $nugetExe = $localNuget } } function Download-Nuget { $tempNuget = "$env:TEMP\codecracker\nuget.exe" if (!(Test-Path "$env:TEMP\codecracker\")) { - md "$env:TEMP\codecracker\" + md "$env:TEMP\codecracker\" | Out-Null } if (Test-Path $localNuget) { if (IsNugetVersion3($localNuget)) { return } @@ -48,7 +48,7 @@ function Download-Nuget { function Import-Psake { $psakeModule = "$PSScriptRoot\packages\psake.4.5.0\tools\psake.psm1" if ((Test-Path $psakeModule) -ne $true) { - . $nugetExe restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot + . "$nugetExe" restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot } Import-Module $psakeModule -force } @@ -56,7 +56,8 @@ function Import-Psake { # statements: $localNuget = "$PSScriptRoot\.nuget\nuget.exe" -$nugetExe = Get-Nuget +$nugetExe = "" +Get-Nuget Import-Psake if ($MyInvocation.UnboundArguments.Count -ne 0) { . $PSScriptRoot\psake.ps1 -taskList ($MyInvocation.UnboundArguments -join " ") From 75a2904613a3cbfb912bbd2b3ef22ef8159be907 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Sun, 12 Mar 2017 17:27:22 +0100 Subject: [PATCH 101/234] Support and tests for dynamic and params added. --- .../Style/TernaryOperatorCodeFixProvider.cs | 36 +-- .../Style/TernaryOperatorTests.cs | 239 ++++++++++++++++-- 2 files changed, 244 insertions(+), 31 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 2f3b6a0c0..8444c0705 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -97,10 +97,10 @@ internal static class TernaryOperatorCodeFixHelper public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, ExpressionSyntax ifStatementCondition, SemanticModel semanticModel) { - var methodCallSimplification = TrySimplifyMethodCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); - if (methodCallSimplification != null) return methodCallSimplification; - var constructorSimplification = TrySimplifyConstructorCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); - if (constructorSimplification != null) return constructorSimplification; + var methodCallArgApplied = TryApplyArgsOnMethodCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (methodCallArgApplied != null) return methodCallArgApplied; + var constructorArgsApplied = TryApplyArgsOnConstructorCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (constructorArgsApplied != null) return constructorArgsApplied; var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); @@ -110,25 +110,30 @@ public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); } - private static ExpressionSyntax TrySimplifyConstructorCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + private static ExpressionSyntax TryApplyArgsOnConstructorCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) { if (ifExpression is ObjectCreationExpressionSyntax && elseExpression is ObjectCreationExpressionSyntax) { - var ifInvocation = ifExpression as ObjectCreationExpressionSyntax; - var elseInvocation = elseExpression as ObjectCreationExpressionSyntax; - var ifMethodinfo = semanticModel.GetSymbolInfo(ifInvocation); - var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation); - if (object.Equals(ifMethodinfo, elseMethodinfo)) //same method and overload + var ifObjCreation = ifExpression as ObjectCreationExpressionSyntax; + var elseObjCreation = elseExpression as ObjectCreationExpressionSyntax; + if ((ifObjCreation.Initializer == null && elseObjCreation.Initializer == null) || + ifObjCreation.Initializer != null && elseObjCreation.Initializer != null && + ifObjCreation.Initializer.GetText().ContentEquals(elseObjCreation.Initializer.GetText())) // Initializer are either absent or text equals { - var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); - if (findSingleArgumentIndexThatDiffers >= 0) - return SyntaxFactory.ObjectCreationExpression(ifInvocation.Type, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel), null); + var ifMethodinfo = semanticModel.GetSymbolInfo(ifObjCreation); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseObjCreation); + if (object.Equals(ifMethodinfo, elseMethodinfo)) //same constructor and overload + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifObjCreation.ArgumentList, elseObjCreation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.ObjectCreationExpression(ifObjCreation.Type, CreateMethodArgumentList(ifStatementCondition, ifObjCreation.ArgumentList, elseObjCreation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel), ifObjCreation.Initializer); + } } } return null; } - private static ExpressionSyntax TrySimplifyMethodCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + private static ExpressionSyntax TryApplyArgsOnMethodCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) { if (ifExpression is InvocationExpressionSyntax && elseExpression is InvocationExpressionSyntax) { @@ -136,7 +141,7 @@ private static ExpressionSyntax TrySimplifyMethodCalls(ExpressionSyntax ifStatem var elseInvocation = elseExpression as InvocationExpressionSyntax; var ifMethodinfo = semanticModel.GetSymbolInfo(ifInvocation.Expression); var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation.Expression); - if (object.Equals(ifMethodinfo, elseMethodinfo)) //same method and overload + if (object.Equals(ifMethodinfo, elseMethodinfo) && ifMethodinfo.CandidateReason != CandidateReason.LateBound) //same method and overload, but not dynamic { if (ifInvocation.Expression.GetText().ContentEquals(elseInvocation.Expression.GetText())) //same 'path' to the invocation { @@ -172,6 +177,7 @@ private static ConditionalExpressionSyntax GetConditionalExpressionForArgument(E private static int FindSingleArgumentIndexThatDiffers(ArgumentListSyntax argList1, ArgumentListSyntax argList2, SemanticModel semanticModel) { + if (argList1.Arguments.Count != argList2.Arguments.Count) return -1; // in case of 'params' var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); var singleMissmatch = zipped.Where(args => { diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 714041c00..c9f42e24f 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -336,8 +336,8 @@ public static void Foo() } [Fact] - public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultChangeToTernaryFixGetsSimplified() - { + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultChangeToTernaryFixGetsArgsApplied() + { var source = @" int Method(int a) => a; @@ -353,7 +353,7 @@ public void Foo() { a = Method(2); } - }".WrapInCSharpClass(); + }".WrapInCSharpClass(); var fixtest = @" int Method(int a) => a; @@ -367,7 +367,7 @@ public void Foo() } [Fact] - public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultWithComplexArgumentEvaluationChangeToTernaryFixGetsSimplified() + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultWithComplexArgumentEvaluationChangeToTernaryFixGetsArgsApplied() { var source = @" int Method(int a) => a; @@ -810,7 +810,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodWithSingleDifferentArgumentGetsSimplified() + public async Task FixWhenReturningWithMethodWithSingleDifferentArgumentGetsArgsApplied() { var source = @" private int Method(int i) => i; @@ -833,7 +833,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereSingleDifferentGetsSimplified() + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereSingleDifferentGetsArgsApplied() { var source = @" private int Method(int i, string t) => i; @@ -856,7 +856,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereMultipleDifferentGetsNotSimplified() + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereMultipleDifferentGetsArgsNotApplied() { var source = @" private int Method(int i, string t) => i; @@ -879,7 +879,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodArgumentsGetCastedWhenSimplified() + public async Task FixWhenReturningWithMethodArgumentsGetCastedWhenGetsArgsApplied() { var source = @" class Base { } @@ -910,7 +910,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithPrefixedMethodGetsSimplified() + public async Task FixWhenReturningWithPrefixedMethodGetsArgsApplied() { var source = @" private int Method(int a) => a; @@ -933,7 +933,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodOfPropertyGetsSimplified() + public async Task FixWhenReturningWithMethodOfPropertyGetsArgsApplied() { var source = @" class A { @@ -962,7 +962,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodOfDifferentPropertyGetsNotSimplified() + public async Task FixWhenReturningWithMethodOfDifferentPropertyGetsArgsNotApplied() { var source = @" class A { @@ -993,7 +993,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodOfSameOverloadGetsSimplified() + public async Task FixWhenReturningWithMethodOfSameOverloadGetsArgsApplied() { var source = @" int Method(int a)=>a; @@ -1018,7 +1018,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodOfDifferentOverloadGetsNotSimplified() + public async Task FixWhenReturningWithMethodOfDifferentOverloadGetsArgsNotApplied() { var source = @" int Method(int a)=>a; @@ -1043,7 +1043,7 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithMethodNestedInMemberAccessGetsNotSimplified() + public async Task FixWhenReturningWithMethodNestedInMemberAccessGetsArgsNotApplied() { var source = @" class A { @@ -1074,10 +1074,113 @@ public int Foo() } [Fact] - public async Task FixWhenReturningWithConstructorGetsSimplified() + public async Task FixWhenReturningWithMethodParamOverloadAndNumerOfArgsAreEqualGetsApplied() + { + var source = @" + private int M(params int[] args) { } + + public int Foo() + { + if (true) + return M(1,1); + else + return M(1,2); + }".WrapInCSharpClass(); + var fixtest = @" + private int M(params int[] args) { } + + public int Foo() + { + return M(1,true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodParamOverloadAndNumerOfArgsAreDifferentGetsNotApplied() { var source = @" + private int M(params int[] args) { } + public int Foo() + { + if (true) + return M(1,1); + else + return M(1,2,3); + }".WrapInCSharpClass(); + var fixtest = @" + private int M(params int[] args) { } + + public int Foo() + { + return true?M(1,1):M(1,2,3); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDynamicObjGetsArgsNotApplied() + { + // Calls on dynamic objects get dispatched during runtime. + // Therefore the semantic would be changed if we apply to arguments + // and casting is involved: + // d.M(new A()) else d.M(new B()) -> d.M(cond?(Base)new A():new B()); + // is not the same as cond?d.M(new A()): d.M(new B()) on dynamic objects. + var source = @" + public class Base {} + public class A: Base {} + public class B: Base {} + + public int Foo() + { + dynamic d = new object(); + if (true) + return d.M(new A()); + else + return d.M(new B()); + }".WrapInCSharpClass(); + var fixtest = @" + public class Base {} + public class A: Base {} + public class B: Base {} + + public int Foo() + { + dynamic d = new object(); + return true?d.M(new A()):d.M(new B()); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDynamicObjGetsArgsNeverApplied() + { + // arguments on dynamic method calls are never applied even if it would be save. + // see comments above for why dynamic is dangerous. + var source = @" + public int Foo() + { + dynamic d = new object(); + if (true) + return d.M(1,1); + else + return d.M(1,2); + }".WrapInCSharpClass(); + var fixtest = @" + public int Foo() + { + dynamic d = new object(); + return true?d.M(1,1):d.M(1,2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorGetsArgsApplied() + { + var source = @" + public System.Collections.Generic.List Foo() { if (true) return new System.Collections.Generic.List(1); @@ -1085,11 +1188,115 @@ public int Foo() return new System.Collections.Generic.List(2); }".WrapInCSharpClass(); var fixtest = @" - public int Foo() + public System.Collections.Generic.List Foo() { return new System.Collections.Generic.List(true?1:2); }".WrapInCSharpClass(); await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task FixWhenReturningWithConstructorWithIdenticalInitializerGetsArgsApplied() + { + var source = @" + public new System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1) { 1 }; + else + return new System.Collections.Generic.List(2) { 1 }; + }".WrapInCSharpClass(); + var fixtest = @" + public new System.Collections.Generic.List Foo() + { + return new System.Collections.Generic.List(true?1:2) { 1 }; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithDifferentInitializerGetsArgsNotApplied() + { + var source = @" + public System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1) { 1 }; + else + return new System.Collections.Generic.List(2) { 1, 2 }; + }".WrapInCSharpClass(); + var fixtest = @" + public System.Collections.Generic.List Foo() + { + return true?new System.Collections.Generic.List(1) { 1 } : new System.Collections.Generic.List(2) { 1, 2 }; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithDifferentOverloadsGetArgsNotApplied() + { + var source = @" + public class A + { + public A(int i) { } + public A(string s) { } + } + public A Foo() + { + if (true) + return new A(1); + else + return new A(""1""); + }".WrapInCSharpClass(); + var fixtest = @" + public class A + { + public A(int i) { } + public A(string s) { } + } + public A Foo() + { + return true?new A(1):new A(""1""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorOfDifferentObjectsGetArgsNotApplied() + { + var source = @" + public class A + { + public A(int i) { } + } + public class B + { + public B(int i) { } + } + + public Object Foo() + { + if (true) + return new A(1); + else + return new B(2); + }".WrapInCSharpClass(); + var fixtest = @" + public class A + { + public A(int i) { } + } + public class B + { + public B(int i) { } + } + + public Object Foo() + { + return true?(object)new A(1):new B(2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From 61dae0431931613fb86479aec29648a409fefb45 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Sun, 12 Mar 2017 17:39:11 +0100 Subject: [PATCH 102/234] Added additional test for overload resolution. --- .../Style/TernaryOperatorTests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index c9f42e24f..c9c86f91c 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -1042,6 +1042,35 @@ public int Foo() await VerifyCSharpFixAsync(source, fixtest); } + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentOverloadButCastingPossibleGetsArgsNotApplied() + { + var source = @" + public class A { } + public class B:A { } + void Method(A a) { }; + void Method(B b) { }; + + public int Foo() + { + if (true) + return Method(new A()); + else + return Method(new B()); + }".WrapInCSharpClass(); + var fixtest = @" + public class A { } + public class B:A { } + void Method(A a) { }; + void Method(B b) { }; + + public int Foo() + { + return true?Method(new A()):Method(new B()); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + [Fact] public async Task FixWhenReturningWithMethodNestedInMemberAccessGetsArgsNotApplied() { From 174493e21c5861977c89dfafb9a38fb8de18558c Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 11 Mar 2017 19:44:11 -0300 Subject: [PATCH 103/234] Evolve build.ps1 to work with Nuget 3 or greater --- build.ps1 | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/build.ps1 b/build.ps1 index 691e90be6..d1a072785 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,29 +1,30 @@ $ErrorActionPreference = "Stop" # functions: -function IsNugetVersion3($theNugetExe) { +function IsNugetVersion3OrAbove($theNugetExe) { try { $nugetText = . $theNugetExe | Out-String } catch { return false } - [regex]$regex = '^NuGet Version: (.*)\n' + [regex]$regex = '^NuGet Version: (\d)\.(\d).*\n' $match = $regex.Match($nugetText) $version = $match.Groups[1].Value - return $version.StartsWith(3) + Write-Host "Nuget major version is $version" + return [System.Convert]::ToInt32($version) -ge 3 } function Get-Nuget { if (gcm nuget -ErrorAction SilentlyContinue) { - if (IsNugetVersion3 'nuget') { - $nugetExe = 'nuget' + if (IsNugetVersion3OrAbove 'nuget') { + $script:nugetExe = 'nuget' } else { Download-Nuget - $nugetExe = $localNuget + $script:nugetExe = $localNuget } } else { Download-Nuget - $nugetExe = $localNuget + $script:nugetExe = $localNuget } } @@ -33,10 +34,10 @@ function Download-Nuget { md "$env:TEMP\codecracker\" | Out-Null } if (Test-Path $localNuget) { - if (IsNugetVersion3($localNuget)) { return } + if (IsNugetVersion3OrAbove($localNuget)) { return } } if (Test-Path $tempNuget) { - if (IsNugetVersion3($tempNuget)) { + if (IsNugetVersion3OrAbove($tempNuget)) { cp $tempNuget $localNuget return } @@ -48,7 +49,8 @@ function Download-Nuget { function Import-Psake { $psakeModule = "$PSScriptRoot\packages\psake.4.5.0\tools\psake.psm1" if ((Test-Path $psakeModule) -ne $true) { - . "$nugetExe" restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot + Write-Host "Restoring $PSScriptRoot\.nuget with $script:nugetExe" + . "$script:nugetExe" restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot } Import-Module $psakeModule -force } From bf783486f04425fba8047e2dbdfc2acd235bae03 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 12 Mar 2017 21:24:08 -0300 Subject: [PATCH 104/234] Add changelog --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31c87d874..8af91802e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Change Log +## [Unreleased](https://github.com/code-cracker/code-cracker/tree/HEAD) + +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.2...HEAD) + +**Closed issues:** + + +## [v1.0.2](https://github.com/code-cracker/code-cracker/tree/v1.0.2) (2017-03-12) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.1...v1.0.2) + +**Implemented enhancements:** + +- VS 2017RC Support [\#856](https://github.com/code-cracker/code-cracker/issues/856) + +**Fixed bugs:** + +- CC0057 UnusedParametersAnalyzer should not be triggered on virtual methods [\#872](https://github.com/code-cracker/code-cracker/issues/872) +- BUG: CC0060 - detected for nested struct in abstract class [\#867](https://github.com/code-cracker/code-cracker/issues/867) +- Bug on CC0120 for the fix when there is a conversion [\#859](https://github.com/code-cracker/code-cracker/issues/859) +- BUG: CC0052 \(Make readonly\) sometimes detects complex value types [\#854](https://github.com/code-cracker/code-cracker/issues/854) +- BUG: CC0052 \(Make readonly\) does not work with lambda expressions and initialized variables [\#853](https://github.com/code-cracker/code-cracker/issues/853) +- "Disposable Field Not Disposed" rule does not recognize null propagation [\#848](https://github.com/code-cracker/code-cracker/issues/848) +- CC0082: ComputeExpressionCodeFixProvider crashs [\#841](https://github.com/code-cracker/code-cracker/issues/841) +- CC0030: Bad grammar in message [\#838](https://github.com/code-cracker/code-cracker/issues/838) +- CC0008: Don't suggest for dynamic objects [\#837](https://github.com/code-cracker/code-cracker/issues/837) +- Bug: Should not use Async methods in analyzers \(CC0029\) [\#821](https://github.com/code-cracker/code-cracker/issues/821) +- BUG: CC0014 converts if y then x += 1 else x =1 to x +=\(if\(y, 1, 1\) [\#798](https://github.com/code-cracker/code-cracker/issues/798) + ## [v1.0.1](https://github.com/code-cracker/code-cracker/tree/v1.0.1) (2016-09-06) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.0...v1.0.1) From c92c0001514ba8e777858714b6417e8b75ab4a92 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 12 Mar 2017 21:36:43 -0300 Subject: [PATCH 105/234] Update vsix --- .../CodeCracker.Vsix/source.extension.vsixmanifest | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index ddd2f9d9d..49925d371 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -25,4 +25,8 @@ This is a community project, free and open source. Everyone is invited to contri + + + + From 9e87cfe904e564da4865bb81719981ba6dedebab Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 12 Mar 2017 21:51:07 -0300 Subject: [PATCH 106/234] Bump version to 1.0.2 --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CSharp/CodeCracker/Properties/AssemblyInfo.cs | 2 +- src/CodeCracker.nuspec | 6 +++--- src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- src/VisualBasic/CodeCracker/CodeCracker.nuspec | 2 +- src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb | 2 +- test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs | 2 +- .../CodeCracker.Test.Common/Properties/AssemblyInfo.cs | 2 +- .../VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index d2b7702fd..940a535fc 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for C# An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index cf2da4160..31a6c4a08 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.CSharp - 1.0.2 + 1.0.3 CodeCracker for C# giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs index a2cbcaa12..3d1250f56 100644 --- a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.2.0")] +[assembly: AssemblyFileVersion("1.0.3.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec index 6ceea0773..61ef261bc 100644 --- a/src/CodeCracker.nuspec +++ b/src/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker - 1.0.2 + 1.0.3 CodeCracker for C# and VB giggio,elemarjr,carloscds giggio,elemarjr,carloscds @@ -19,8 +19,8 @@ This is a community project, free and open source. Everyone is invited to contri Copyright CodeCracker 2014-2016 roslyn, analyzers - - + + diff --git a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs index 9bee0ce03..c63e0d98f 100644 --- a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs +++ b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs @@ -14,6 +14,6 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.2.0")] +[assembly: AssemblyFileVersion("1.0.3.0")] [assembly: InternalsVisibleTo("CodeCracker.Test.CSharp")] [assembly: InternalsVisibleTo("CodeCracker.Test.VisualBasic")] \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index 49925d371..4f7911589 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for Visual Basic An analyzer library for VB that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index ecb28d922..0b6a31ec4 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -2,7 +2,7 @@ codecracker.VisualBasic - 1.0.2 + 1.0.3 CodeCracker for Visual Basic giggio,elemarjr,carloscds giggio,elemarjr,carloscds diff --git a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb index 1425d7339..a3478becf 100644 --- a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb +++ b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb @@ -14,5 +14,5 @@ Imports System.Runtime.InteropServices - + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs index 8809cfb5b..92983d5f5 100644 --- a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs +++ b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.2.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.0.3.0")] \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs index 2a6956dbe..e7a08f024 100644 --- a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs @@ -14,4 +14,4 @@ [assembly: ComVisible(false)] [assembly: NeutralResourcesLanguage("en-us")] [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.2.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.0.3.0")] \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb index f7d706ba8..2b5faf79b 100644 --- a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb +++ b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb @@ -14,4 +14,4 @@ Imports System.Runtime.InteropServices - \ No newline at end of file + \ No newline at end of file From b63870c10e19a71b80cf78a46085cf316a81364d Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Mon, 27 Feb 2017 19:17:58 +0100 Subject: [PATCH 107/234] Tenary operator: apply to arguments. Fix: #522 --- .../Style/TernaryOperatorCodeFixProvider.cs | 98 ++- .../Style/TernaryOperatorTests.cs | 604 ++++++++++++++++++ 2 files changed, 695 insertions(+), 7 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 97ebd2e3f..8444c0705 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System; namespace CodeCracker.CSharp.Style { @@ -37,11 +38,10 @@ private static async Task MakeTernaryAsync(Document document, Diagnost var elseStatement = ifStatement.Else; var returnStatementInsideElse = (ReturnStatementSyntax)(elseStatement.Statement is BlockSyntax ? ((BlockSyntax)elseStatement.Statement).Statements.Single() : elseStatement.Statement); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - ExpressionSyntax trueExpression, falseExpression; - TernaryOperatorCodeFixHelper.CreateExpressions(returnStatementInsideIf.Expression, returnStatementInsideElse.Expression, semanticModel, out trueExpression, out falseExpression); + var conditionalExpression = TernaryOperatorCodeFixHelper.CreateExpressions(returnStatementInsideIf.Expression, returnStatementInsideElse.Expression, ifStatement.Condition, semanticModel); var ternary = SyntaxFactory.ReturnStatement( - SyntaxFactory.ConditionalExpression(ifStatement.Condition, trueExpression, falseExpression)) + conditionalExpression) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); @@ -76,14 +76,13 @@ private static async Task MakeTernaryAsync(Document document, Diagnost var assignmentExpressionInsideIf = (AssignmentExpressionSyntax)expressionInsideIf.Expression; var assignmentExpressionInsideElse = (AssignmentExpressionSyntax)expressionInsideElse.Expression; var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - ExpressionSyntax trueExpression, falseExpression; - TernaryOperatorCodeFixHelper.CreateExpressions(assignmentExpressionInsideIf.Right, assignmentExpressionInsideElse.Right, semanticModel, out trueExpression, out falseExpression); + var conditionalExpression = TernaryOperatorCodeFixHelper.CreateExpressions(assignmentExpressionInsideIf.Right, assignmentExpressionInsideElse.Right, ifStatement.Condition, semanticModel); var ternary = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( assignmentExpressionInsideIf.Kind(), assignmentExpressionInsideIf.Left, - SyntaxFactory.ConditionalExpression(ifStatement.Condition, trueExpression, falseExpression))) + conditionalExpression)) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); @@ -95,13 +94,98 @@ private static async Task MakeTernaryAsync(Document document, Diagnost internal static class TernaryOperatorCodeFixHelper { - public static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel, out ExpressionSyntax trueExpression, out ExpressionSyntax falseExpression) + public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, ExpressionSyntax ifStatementCondition, SemanticModel semanticModel) + { + + var methodCallArgApplied = TryApplyArgsOnMethodCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (methodCallArgApplied != null) return methodCallArgApplied; + var constructorArgsApplied = TryApplyArgsOnConstructorCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (constructorArgsApplied != null) return constructorArgsApplied; + var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); + var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); + var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); + ExpressionSyntax trueExpression; ExpressionSyntax falseExpression; + CreateExpressions(ifExpression, elseExpression, ifTypeInfo.Type, elseTypeInfo.Type, + ifTypeInfo.ConvertedType, elseTypeInfo.ConvertedType, typeSyntax, semanticModel, out trueExpression, out falseExpression); + return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); + } + + private static ExpressionSyntax TryApplyArgsOnConstructorCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + { + if (ifExpression is ObjectCreationExpressionSyntax && elseExpression is ObjectCreationExpressionSyntax) + { + var ifObjCreation = ifExpression as ObjectCreationExpressionSyntax; + var elseObjCreation = elseExpression as ObjectCreationExpressionSyntax; + if ((ifObjCreation.Initializer == null && elseObjCreation.Initializer == null) || + ifObjCreation.Initializer != null && elseObjCreation.Initializer != null && + ifObjCreation.Initializer.GetText().ContentEquals(elseObjCreation.Initializer.GetText())) // Initializer are either absent or text equals + { + var ifMethodinfo = semanticModel.GetSymbolInfo(ifObjCreation); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseObjCreation); + if (object.Equals(ifMethodinfo, elseMethodinfo)) //same constructor and overload + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifObjCreation.ArgumentList, elseObjCreation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.ObjectCreationExpression(ifObjCreation.Type, CreateMethodArgumentList(ifStatementCondition, ifObjCreation.ArgumentList, elseObjCreation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel), ifObjCreation.Initializer); + } + } + } + return null; + } + + private static ExpressionSyntax TryApplyArgsOnMethodCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + { + if (ifExpression is InvocationExpressionSyntax && elseExpression is InvocationExpressionSyntax) + { + var ifInvocation = ifExpression as InvocationExpressionSyntax; + var elseInvocation = elseExpression as InvocationExpressionSyntax; + var ifMethodinfo = semanticModel.GetSymbolInfo(ifInvocation.Expression); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation.Expression); + if (object.Equals(ifMethodinfo, elseMethodinfo) && ifMethodinfo.CandidateReason != CandidateReason.LateBound) //same method and overload, but not dynamic + { + if (ifInvocation.Expression.GetText().ContentEquals(elseInvocation.Expression.GetText())) //same 'path' to the invocation + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.InvocationExpression(ifInvocation.Expression, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel)); + } + } + } + return null; + } + + private static ArgumentListSyntax CreateMethodArgumentList(ExpressionSyntax ifStatementCondition, ArgumentListSyntax argList1, ArgumentListSyntax argList2, int argumentIndexThatDiffers, SemanticModel semanticModel) + { + var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); + var argSelector = zipped.Select((args, i) => + (i == argumentIndexThatDiffers) ? + SyntaxFactory.Argument(GetConditionalExpressionForArgument(ifStatementCondition, args.a1.Expression, args.a2.Expression, semanticModel)) + : args.a1); + return SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argSelector)); + } + + private static ConditionalExpressionSyntax GetConditionalExpressionForArgument(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) { var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); + ExpressionSyntax trueExpression; ExpressionSyntax falseExpression; CreateExpressions(ifExpression, elseExpression, ifTypeInfo.Type, elseTypeInfo.Type, ifTypeInfo.ConvertedType, elseTypeInfo.ConvertedType, typeSyntax, semanticModel, out trueExpression, out falseExpression); + return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); + } + + private static int FindSingleArgumentIndexThatDiffers(ArgumentListSyntax argList1, ArgumentListSyntax argList2, SemanticModel semanticModel) + { + if (argList1.Arguments.Count != argList2.Arguments.Count) return -1; // in case of 'params' + var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); + var singleMissmatch = zipped.Where(args => + { + var a1Text = args.a1.GetText(); + var a2Text = args.a2.GetText(); + return !a1Text.ContentEquals(a2Text); + }).Take(2).ToList(); + return (singleMissmatch.Count == 1) ? singleMissmatch[0].i : -1; } private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 68d90f96d..c9c86f91c 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -334,6 +334,68 @@ public static void Foo() "; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultChangeToTernaryFixGetsArgsApplied() + { + var source = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + if (something) + { + a = Method(1); + } + else + { + a = Method(2); + } + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + a = Method(something?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultWithComplexArgumentEvaluationChangeToTernaryFixGetsArgsApplied() + { + var source = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + if (something) + { + a = Method(1); + } + else + { + a = Method(2 + 2); + } + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + a = Method(something?1:2 + 2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } public class TernaryOperatorWithReturnTests : CodeFixVerifier @@ -723,5 +785,547 @@ public static Base Foo() "; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenReturnStatementContainsMethodCallAnalyzerCreatesDiagnostic() + { + var source = @" + private int Method(int i) => i; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), + Message = "You can use a ternary operator.", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 17) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithSingleDifferentArgumentGetsArgsApplied() + { + var source = @" + private int Method(int i) => i; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i) => i; + + public int Foo() + { + return Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereSingleDifferentGetsArgsApplied() + { + var source = @" + private int Method(int i, string t) => i; + + public int Foo() + { + if (true) + return Method(1, ""hello""); + else + return Method(2, ""hello""); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i, string t) => i; + + public int Foo() + { + return Method(true?1:2, ""hello""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereMultipleDifferentGetsArgsNotApplied() + { + var source = @" + private int Method(int i, string t) => i; + + public int Foo() + { + if (true) + return Method(1, ""hello1""); + else + return Method(2, ""hello2""); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i, string t) => i; + + public int Foo() + { + return true?Method(1,""hello1""):Method(2, ""hello2""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodArgumentsGetCastedWhenGetsArgsApplied() + { + var source = @" + class Base { } + class A : Base { } + class B : Base { } + + private int Method(Base b, string t) => 1; + + public int Foo() + { + if (true) + return Method(new A(), ""hello""); + else + return Method(new B(), ""hello""); + }".WrapInCSharpClass(); + var fixtest = @" + class Base { } + class A : Base { } + class B : Base { } + + private int Method(Base b, string t) => 1; + + public int Foo() + { + return Method(true?(Base)new A():new B(),""hello""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithPrefixedMethodGetsArgsApplied() + { + var source = @" + private int Method(int a) => a; + + public int Foo() + { + if (true) + return this.Method(1); + else + return this.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int a) => a; + + public int Foo() + { + return this.Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfPropertyGetsArgsApplied() + { + var source = @" + class A { + private int Method(int a) => a; + } + + public int Foo() + { + var a=new A(); + if (true) + return a.Method(1); + else + return a.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + class A { + private int Method(int a) => a; + } + + public int Foo() + { + var a=new A(); + return a.Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentPropertyGetsArgsNotApplied() + { + var source = @" + class A { + public int Method(int a) => a; + } + A Prop1 { get { return new A(); } } + A Prop2 { get { return new A(); } } + + public int Foo() + { + if (true) + return this.Prop1.Method(1); + else + return this.Prop2.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + class A { + public int Method(int a) => a; + } + A Prop1 { get { return new A(); } } + A Prop2 { get { return new A(); } } + + public int Foo() + { + return true?this.Prop1.Method(1):this.Prop2.Method(2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfSameOverloadGetsArgsApplied() + { + var source = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + return Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentOverloadGetsArgsNotApplied() + { + var source = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(""2""); + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + return true?Method(1):Method(""2""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentOverloadButCastingPossibleGetsArgsNotApplied() + { + var source = @" + public class A { } + public class B:A { } + void Method(A a) { }; + void Method(B b) { }; + + public int Foo() + { + if (true) + return Method(new A()); + else + return Method(new B()); + }".WrapInCSharpClass(); + var fixtest = @" + public class A { } + public class B:A { } + void Method(A a) { }; + void Method(B b) { }; + + public int Foo() + { + return true?Method(new A()):Method(new B()); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodNestedInMemberAccessGetsArgsNotApplied() + { + var source = @" + class A { + public int Prop { get; } + } + + A GetA(int i) => new A(); + + public int Foo() + { + if (true) + return GetA(1).Prop; + else + return GetA(2).Prop; + }".WrapInCSharpClass(); + var fixtest = @" + class A { + public int Prop { get; } + } + + A GetA(int i) => new A(); + + public int Foo() + { + return true?GetA(1).Prop:GetA(2).Prop; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodParamOverloadAndNumerOfArgsAreEqualGetsApplied() + { + var source = @" + private int M(params int[] args) { } + + public int Foo() + { + if (true) + return M(1,1); + else + return M(1,2); + }".WrapInCSharpClass(); + var fixtest = @" + private int M(params int[] args) { } + + public int Foo() + { + return M(1,true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodParamOverloadAndNumerOfArgsAreDifferentGetsNotApplied() + { + var source = @" + private int M(params int[] args) { } + + public int Foo() + { + if (true) + return M(1,1); + else + return M(1,2,3); + }".WrapInCSharpClass(); + var fixtest = @" + private int M(params int[] args) { } + + public int Foo() + { + return true?M(1,1):M(1,2,3); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDynamicObjGetsArgsNotApplied() + { + // Calls on dynamic objects get dispatched during runtime. + // Therefore the semantic would be changed if we apply to arguments + // and casting is involved: + // d.M(new A()) else d.M(new B()) -> d.M(cond?(Base)new A():new B()); + // is not the same as cond?d.M(new A()): d.M(new B()) on dynamic objects. + var source = @" + public class Base {} + public class A: Base {} + public class B: Base {} + + public int Foo() + { + dynamic d = new object(); + if (true) + return d.M(new A()); + else + return d.M(new B()); + }".WrapInCSharpClass(); + var fixtest = @" + public class Base {} + public class A: Base {} + public class B: Base {} + + public int Foo() + { + dynamic d = new object(); + return true?d.M(new A()):d.M(new B()); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDynamicObjGetsArgsNeverApplied() + { + // arguments on dynamic method calls are never applied even if it would be save. + // see comments above for why dynamic is dangerous. + var source = @" + public int Foo() + { + dynamic d = new object(); + if (true) + return d.M(1,1); + else + return d.M(1,2); + }".WrapInCSharpClass(); + var fixtest = @" + public int Foo() + { + dynamic d = new object(); + return true?d.M(1,1):d.M(1,2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorGetsArgsApplied() + { + var source = @" + public System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1); + else + return new System.Collections.Generic.List(2); + }".WrapInCSharpClass(); + var fixtest = @" + public System.Collections.Generic.List Foo() + { + return new System.Collections.Generic.List(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithIdenticalInitializerGetsArgsApplied() + { + var source = @" + public new System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1) { 1 }; + else + return new System.Collections.Generic.List(2) { 1 }; + }".WrapInCSharpClass(); + var fixtest = @" + public new System.Collections.Generic.List Foo() + { + return new System.Collections.Generic.List(true?1:2) { 1 }; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithDifferentInitializerGetsArgsNotApplied() + { + var source = @" + public System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1) { 1 }; + else + return new System.Collections.Generic.List(2) { 1, 2 }; + }".WrapInCSharpClass(); + var fixtest = @" + public System.Collections.Generic.List Foo() + { + return true?new System.Collections.Generic.List(1) { 1 } : new System.Collections.Generic.List(2) { 1, 2 }; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithDifferentOverloadsGetArgsNotApplied() + { + var source = @" + public class A + { + public A(int i) { } + public A(string s) { } + } + public A Foo() + { + if (true) + return new A(1); + else + return new A(""1""); + }".WrapInCSharpClass(); + var fixtest = @" + public class A + { + public A(int i) { } + public A(string s) { } + } + public A Foo() + { + return true?new A(1):new A(""1""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorOfDifferentObjectsGetArgsNotApplied() + { + var source = @" + public class A + { + public A(int i) { } + } + public class B + { + public B(int i) { } + } + + public Object Foo() + { + if (true) + return new A(1); + else + return new B(2); + }".WrapInCSharpClass(); + var fixtest = @" + public class A + { + public A(int i) { } + } + public class B + { + public B(int i) { } + } + + public Object Foo() + { + return true?(object)new A(1):new B(2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From 1e6d745cac04c93f0bc303b14835df2f63f375a3 Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:04:58 -0700 Subject: [PATCH 108/234] Update grammar in StaticConstructorExceptionAnalyzer.cs #839 --- .../Design/StaticConstructorExceptionAnalyzer.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs b/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs index 946cae300..c8a9f2f23 100644 --- a/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs @@ -10,13 +10,11 @@ namespace CodeCracker.CSharp.Design [DiagnosticAnalyzer(LanguageNames.CSharp)] public class StaticConstructorExceptionAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Don't throw exception inside static constructors."; - internal const string MessageFormat = "Don't throw exception inside static constructors."; + internal const string Title = "Don't throw exceptions inside static constructors."; + internal const string MessageFormat = "Don't throw exceptions inside static constructors."; internal const string Category = SupportedCategories.Design; - const string Description = "Static constructor are called before the first time a class is used but the " - + "caller doesn't control when exactly.\r\n" - + "Exception thrown in this context force callers to use 'try' block around any useage of the class " - + "and should be avoided."; + const string Description = "Static constructors are called before a class is used for the first time. Exceptions thrown " + + "in static constructors force the use of a try block and should be avoided."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.StaticConstructorException.ToDiagnosticId(), @@ -49,4 +47,4 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(Diagnostic.Create(Rule, @throw.GetLocation(), ctor.Identifier.Text)); } } -} \ No newline at end of file +} From 2e74e2698ede0d57426192deed7b5a652eaa3ed8 Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:06:30 -0700 Subject: [PATCH 109/234] Update grammar in StaticConstructorExceptionAnalyzer.vb #839 --- .../Design/StaticConstructorExceptionAnalyzer.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb b/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb index 72799cbd9..3cfaab1f3 100644 --- a/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb @@ -9,11 +9,11 @@ Namespace Design Inherits DiagnosticAnalyzer Public Shared ReadOnly Id As String = DiagnosticId.StaticConstructorException.ToDiagnosticId() - Public Const Title As String = "Don't throw exception inside static constructors." + Public Const Title As String = "Don't throw exceptions inside static constructors." Public Const MessageFormat As String = "Don't throw exceptions inside static constructors." Public Const Category As String = SupportedCategories.Design - Public Const Description As String = "Static constructor are called before the first time a class is used but the caller doesn't control when exactly. -Exception thrown in this context forces callers to use 'try' block around any useage of the class and should be avoided." + Public Const Description As String = "Static constructors are called before a class is used for the first time. Exceptions thrown + in static constructors force the use of a try block and should be avoided." Protected Shared Rule As DiagnosticDescriptor = New DiagnosticDescriptor( Id, Title, From 05ef8216052afc705d7de3abc3f4a6c7780cbcae Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:08:11 -0700 Subject: [PATCH 110/234] Update grammar in StaticConstructorExceptionAnalyzer.cs #839 From 089f3a6cff713e81d485d0c5c534b438d9077601 Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:23:19 -0700 Subject: [PATCH 111/234] Update grammar in StaticConstructorExceptionTests.cs #839 --- .../Design/StaticConstructorExceptionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs b/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs index 5672bd5a9..f6ba9d8a0 100644 --- a/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs @@ -22,7 +22,7 @@ static MyClass() var expected = new DiagnosticResult { Id = DiagnosticId.StaticConstructorException.ToDiagnosticId(), - Message = "Don't throw exception inside static constructors.", + Message = "Don't throw exceptions inside static constructors.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } }; @@ -149,4 +149,4 @@ static MyClass2() await VerifyCSharpFixAllAsync(new string[] { source1, source2 }, new string[] { fixtest1, fixtest2 }); } } -} \ No newline at end of file +} From 0459cc5ef6c1d86e60f4248c40184868b5c44deb Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:48:57 -0700 Subject: [PATCH 112/234] Update grammar in StringBuilderInLoopAnalyzer.cs #839 --- .../CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs b/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs index 27427a1f3..60960be01 100644 --- a/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs @@ -14,8 +14,7 @@ public class StringBuilderInLoopAnalyzer : DiagnosticAnalyzer internal const string Title = "Don't concatenate strings in loops"; internal const string MessageFormat = "Don't concatenate '{0}' in a loop"; internal const string Category = SupportedCategories.Performance; - const string Description = "Do not concatenate a string on a loop. It will alocate a lot of memory." - + "Use a StringBuilder instead. It will will require less allocation, less garbage collector work, less CPU cycles, and less overall time."; + const string Description = "Don't concatenate strings in a loop. Using a StringBuilder will require less memory and time."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), @@ -84,4 +83,4 @@ private static void AnalyzeAssignment(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(diagnostic); } } -} \ No newline at end of file +} From 0dc0321d89a6a27da2b02cf119f5e91dc8497bbf Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:50:00 -0700 Subject: [PATCH 113/234] Update grammar in StringBuilderInLoopAnalyzer.vb #839 --- .../CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb b/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb index e00b20f13..36c1a1ac1 100644 --- a/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb @@ -13,7 +13,7 @@ Namespace Performance Public Const Title As String = "Don't concatenate strings in loops" Public Const MessageFormat As String = "Don't concatenate '{0}' in a loop." Public Const Category As String = SupportedCategories.Performance - Public Const Description As String = "Do not concatenate a string in a loop. It will allocate a lot of memory. Use a StringBuilder instead. It will require less allocation, less garbage collection work, less CPU cycles, and less overall time." + Public Const Description As String = "Don't concatenate strings in a loop. Using a StringBuilder will require less memory and time." Protected Shared Rule As DiagnosticDescriptor = New DiagnosticDescriptor( Id, Title, @@ -71,4 +71,4 @@ Namespace Performance context.ReportDiagnostic(diag) End Sub End Class -End Namespace \ No newline at end of file +End Namespace From 51fbe1cd7ce47e3fd5c1f0d93a70302fb1295e7b Mon Sep 17 00:00:00 2001 From: sdygert Date: Sat, 18 Mar 2017 07:47:05 -0700 Subject: [PATCH 114/234] Update grammar in RemovePrivateMethodNeverUsedAnalyzer.cs #839 --- .../CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs index 40b86f79d..25bd20246 100644 --- a/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs @@ -16,7 +16,7 @@ public class RemovePrivateMethodNeverUsedAnalyzer : DiagnosticAnalyzer internal const string Title = "Unused Method"; internal const string Message = "Method is not used."; internal const string Category = SupportedCategories.Usage; - const string Description = "When a private method declared does not used might bring incorrect conclusions."; + const string Description = "Unused private methods can be safely removed as they are unnecessary."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.RemovePrivateMethodNeverUsed.ToDiagnosticId(), @@ -126,4 +126,4 @@ private static bool IsMainMethodEntryPoint(MethodDeclarationSyntax methodTarget, return true; } } -} \ No newline at end of file +} From d7fe7955f96d2e64a76c00a1982c83dd94282739 Mon Sep 17 00:00:00 2001 From: sdygert Date: Sat, 18 Mar 2017 07:47:31 -0700 Subject: [PATCH 115/234] Update grammar in RemovePrivateMethodNeverUsedAnalyzer.vb #839 --- .../CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb b/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb index e1ecd9068..652a83ca7 100644 --- a/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.vb @@ -11,7 +11,7 @@ Namespace Usage Friend Const Title = "Unused Method" Friend Const Message = "Method is not used." - Private Const Description = "When a private method is declared but not used, remove it to avoid confusion." + Private Const Description = "Unused private methods can be safely removed as they are unnecessary." Friend Shared Rule As New DiagnosticDescriptor( DiagnosticId.RemovePrivateMethodNeverUsed.ToDiagnosticId(), From b71177cbde7855104f2334e9d5c8b3cf815c377c Mon Sep 17 00:00:00 2001 From: sdygert Date: Sat, 18 Mar 2017 07:54:39 -0700 Subject: [PATCH 116/234] Update grammar in RegexAnalyzer.cs #839 --- src/CSharp/CodeCracker/Usage/RegexAnalyzer.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/RegexAnalyzer.cs b/src/CSharp/CodeCracker/Usage/RegexAnalyzer.cs index 6ce7c1a5d..41393ac96 100644 --- a/src/CSharp/CodeCracker/Usage/RegexAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/RegexAnalyzer.cs @@ -10,11 +10,10 @@ namespace CodeCracker.CSharp.Usage [DiagnosticAnalyzer(LanguageNames.CSharp)] public class RegexAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Your Regex expression is wrong"; + internal const string Title = "Your regex expression is incorrect"; internal const string MessageFormat = "{0}"; internal const string Category = SupportedCategories.Naming; - const string Description = "This diagnostic compile the Regex expression and trigger if the compilation fail " - + "by throwing an exception."; + const string Description = "There is an error in your regex expression."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.Regex.ToDiagnosticId(), @@ -63,4 +62,4 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) } } } -} \ No newline at end of file +} From 0b1a1783aa94fa2a09622117036b42677c8727cc Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:48:57 -0700 Subject: [PATCH 117/234] Update grammar in StringBuilderInLoopAnalyzer.cs #839 --- .../CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs b/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs index 27427a1f3..60960be01 100644 --- a/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/StringBuilderInLoopAnalyzer.cs @@ -14,8 +14,7 @@ public class StringBuilderInLoopAnalyzer : DiagnosticAnalyzer internal const string Title = "Don't concatenate strings in loops"; internal const string MessageFormat = "Don't concatenate '{0}' in a loop"; internal const string Category = SupportedCategories.Performance; - const string Description = "Do not concatenate a string on a loop. It will alocate a lot of memory." - + "Use a StringBuilder instead. It will will require less allocation, less garbage collector work, less CPU cycles, and less overall time."; + const string Description = "Don't concatenate strings in a loop. Using a StringBuilder will require less memory and time."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), @@ -84,4 +83,4 @@ private static void AnalyzeAssignment(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(diagnostic); } } -} \ No newline at end of file +} From 7b3122aefb4a3f1ff184d3ef0f3a85af8be2e1c0 Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:50:00 -0700 Subject: [PATCH 118/234] Update grammar in StringBuilderInLoopAnalyzer.vb #839 --- .../CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb b/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb index e00b20f13..36c1a1ac1 100644 --- a/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Performance/StringBuilderInLoopAnalyzer.vb @@ -13,7 +13,7 @@ Namespace Performance Public Const Title As String = "Don't concatenate strings in loops" Public Const MessageFormat As String = "Don't concatenate '{0}' in a loop." Public Const Category As String = SupportedCategories.Performance - Public Const Description As String = "Do not concatenate a string in a loop. It will allocate a lot of memory. Use a StringBuilder instead. It will require less allocation, less garbage collection work, less CPU cycles, and less overall time." + Public Const Description As String = "Don't concatenate strings in a loop. Using a StringBuilder will require less memory and time." Protected Shared Rule As DiagnosticDescriptor = New DiagnosticDescriptor( Id, Title, @@ -71,4 +71,4 @@ Namespace Performance context.ReportDiagnostic(diag) End Sub End Class -End Namespace \ No newline at end of file +End Namespace From 1699a3178249cee656541bd3d885a30f519dec2c Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:04:58 -0700 Subject: [PATCH 119/234] Update grammar in StaticConstructorExceptionAnalyzer.cs #839 --- .../Design/StaticConstructorExceptionAnalyzer.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs b/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs index 946cae300..c8a9f2f23 100644 --- a/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/StaticConstructorExceptionAnalyzer.cs @@ -10,13 +10,11 @@ namespace CodeCracker.CSharp.Design [DiagnosticAnalyzer(LanguageNames.CSharp)] public class StaticConstructorExceptionAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Don't throw exception inside static constructors."; - internal const string MessageFormat = "Don't throw exception inside static constructors."; + internal const string Title = "Don't throw exceptions inside static constructors."; + internal const string MessageFormat = "Don't throw exceptions inside static constructors."; internal const string Category = SupportedCategories.Design; - const string Description = "Static constructor are called before the first time a class is used but the " - + "caller doesn't control when exactly.\r\n" - + "Exception thrown in this context force callers to use 'try' block around any useage of the class " - + "and should be avoided."; + const string Description = "Static constructors are called before a class is used for the first time. Exceptions thrown " + + "in static constructors force the use of a try block and should be avoided."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.StaticConstructorException.ToDiagnosticId(), @@ -49,4 +47,4 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(Diagnostic.Create(Rule, @throw.GetLocation(), ctor.Identifier.Text)); } } -} \ No newline at end of file +} From c1d348985b116736f9ba1092ac05d1de1b47d269 Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:06:30 -0700 Subject: [PATCH 120/234] Update grammar in StaticConstructorExceptionAnalyzer.vb #839 --- .../Design/StaticConstructorExceptionAnalyzer.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb b/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb index 72799cbd9..3cfaab1f3 100644 --- a/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb +++ b/src/VisualBasic/CodeCracker/Design/StaticConstructorExceptionAnalyzer.vb @@ -9,11 +9,11 @@ Namespace Design Inherits DiagnosticAnalyzer Public Shared ReadOnly Id As String = DiagnosticId.StaticConstructorException.ToDiagnosticId() - Public Const Title As String = "Don't throw exception inside static constructors." + Public Const Title As String = "Don't throw exceptions inside static constructors." Public Const MessageFormat As String = "Don't throw exceptions inside static constructors." Public Const Category As String = SupportedCategories.Design - Public Const Description As String = "Static constructor are called before the first time a class is used but the caller doesn't control when exactly. -Exception thrown in this context forces callers to use 'try' block around any useage of the class and should be avoided." + Public Const Description As String = "Static constructors are called before a class is used for the first time. Exceptions thrown + in static constructors force the use of a try block and should be avoided." Protected Shared Rule As DiagnosticDescriptor = New DiagnosticDescriptor( Id, Title, From 67e4081bd90b48f57365fa28ed85879805e9e2e1 Mon Sep 17 00:00:00 2001 From: sdygert Date: Wed, 15 Mar 2017 19:23:19 -0700 Subject: [PATCH 121/234] Update grammar in StaticConstructorExceptionTests.cs #839 --- .../Design/StaticConstructorExceptionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs b/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs index 5672bd5a9..f6ba9d8a0 100644 --- a/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs @@ -22,7 +22,7 @@ static MyClass() var expected = new DiagnosticResult { Id = DiagnosticId.StaticConstructorException.ToDiagnosticId(), - Message = "Don't throw exception inside static constructors.", + Message = "Don't throw exceptions inside static constructors.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } }; @@ -149,4 +149,4 @@ static MyClass2() await VerifyCSharpFixAllAsync(new string[] { source1, source2 }, new string[] { fixtest1, fixtest2 }); } } -} \ No newline at end of file +} From 62ecc7729f766f781a3eb07da4120a78eb57e4ca Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 19 Mar 2017 12:25:54 -0300 Subject: [PATCH 122/234] Update dependencies This will enable tests to run in VS again, including live unit testing. We had to roll back Microsoft.CodeAnalysis.Analyzers, because it conflicted with other packages, we might have to upgrade them all to 1.1.0 so that we don't get those nasty build warnings. --- build.targets.ps1 | 2 +- src/CSharp/CodeCracker/CodeCracker.csproj | 8 ++-- src/CSharp/CodeCracker/packages.config | 4 +- .../CodeCracker.Common.csproj | 8 ++-- src/Common/CodeCracker.Common/packages.config | 4 +- .../CodeCracker/CodeCracker.vbproj | 8 ++-- src/VisualBasic/CodeCracker/packages.config | 4 +- .../CodeCracker.Test/CodeCracker.Test.csproj | 45 ++++++++--------- test/CSharp/CodeCracker.Test/packages.config | 22 ++++----- .../CodeCracker.Test.Common.csproj | 48 +++++++------------ .../CodeCracker.Test.Common/packages.config | 24 +++++----- .../CodeCracker.Test/CodeCracker.Test.vbproj | 41 +++++++--------- .../CodeCracker.Test/packages.config | 22 ++++----- 13 files changed, 106 insertions(+), 134 deletions(-) diff --git a/build.targets.ps1 b/build.targets.ps1 index 42ee817bb..430e72c21 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -23,7 +23,7 @@ Properties { $testDirVB = "$testDir\VisualBasic\CodeCracker.Test\bin\Release" $logDir = "$rootDir\log" $outputXml = "$logDir\CodeCoverageResults.xml" - $reportGeneratorExe = "$packagesDir\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe" + $reportGeneratorExe = "$packagesDir\ReportGenerator.2.5.6\tools\ReportGenerator.exe" $coverageReportDir = "$logDir\codecoverage\" $coverallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" $isRelease = $isAppVeyor -and (($env:APPVEYOR_REPO_BRANCH -eq "release") -or ($env:APPVEYOR_REPO_TAG -eq "true")) diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index e1a60a05e..762e6c620 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -221,10 +221,10 @@ - - - - + + + + diff --git a/src/CSharp/CodeCracker/packages.config b/src/CSharp/CodeCracker/packages.config index 26624b6d1..d1bbcab2c 100644 --- a/src/CSharp/CodeCracker/packages.config +++ b/src/CSharp/CodeCracker/packages.config @@ -1,7 +1,7 @@  - - + + diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index 6ecee6f01..3426e7d12 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -70,10 +70,10 @@ - - - - + + + + diff --git a/src/Common/CodeCracker.Common/packages.config b/src/Common/CodeCracker.Common/packages.config index 564e6399a..d8681f9ca 100644 --- a/src/Common/CodeCracker.Common/packages.config +++ b/src/Common/CodeCracker.Common/packages.config @@ -1,7 +1,7 @@  - - + + diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index ba1b36a08..e2deff9b9 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -162,10 +162,10 @@ - - - - + + + + diff --git a/src/VisualBasic/CodeCracker/packages.config b/src/VisualBasic/CodeCracker/packages.config index 06a0521ef..20b3df7df 100644 --- a/src/VisualBasic/CodeCracker/packages.config +++ b/src/VisualBasic/CodeCracker/packages.config @@ -1,7 +1,7 @@  - - + + diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index b17ba4a79..e0e64dccb 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -1,6 +1,6 @@  - + Debug AnyCPU @@ -40,13 +40,11 @@ false - - ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.dll - True + + ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.dll - - ..\..\..\packages\FluentAssertions.4.3.2\lib\net45\FluentAssertions.Core.dll - True + + ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.Core.dll ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.dll @@ -68,9 +66,8 @@ ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True - - ..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll - True + + ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll @@ -108,20 +105,16 @@ - ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True + ..\..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll - - ..\..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll - True + + ..\..\..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll - - ..\..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll - True + + ..\..\..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll - - ..\..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll - True + + ..\..\..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll @@ -235,17 +228,17 @@ - - - - + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - \ No newline at end of file + From 099159dfedd4c57105d26a196bde2c3c5833c902 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 19 Mar 2017 12:47:27 -0300 Subject: [PATCH 134/234] Fix xunit console location in script --- build.targets.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.targets.ps1 b/build.targets.ps1 index 430e72c21..d5c0cc057 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -15,7 +15,7 @@ Properties { $nupkgPathCS = "$rootDir\src\CSharp\CodeCracker.CSharp.{0}.nupkg" $nupkgPathVB = "$rootDir\src\VisualBasic\CodeCracker.VisualBasic.{0}.nupkg" $nupkgPathJoint = "$rootDir\CodeCracker.{0}.nupkg" - $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" + $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" $openCoverExe = "$packagesDir\OpenCover.4.6.519\tools\OpenCover.Console.exe" $testDllCS = "CodeCracker.Test.CSharp.dll" $testDllVB = "CodeCracker.Test.VisualBasic.dll" @@ -223,4 +223,4 @@ function RunTestWithCoverage($fullTestDllPaths) { Write-Host -ForegroundColor DarkBlue "Uploading coverage report to Coveralls.io" Exec { . $coverallsNetExe --opencover $outputXml --full-sources } } -} \ No newline at end of file +} From ac872ca9ebdd3db4aece2c60ef9e80b4173c42f9 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 19 Mar 2017 13:09:32 -0300 Subject: [PATCH 135/234] Fix test run scripts --- runTestsCS.ps1 | 2 +- runTestsVB.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runTestsCS.ps1 b/runTestsCS.ps1 index 2131ad77c..930bdccb4 100644 --- a/runTestsCS.ps1 +++ b/runTestsCS.ps1 @@ -2,7 +2,7 @@ param([String]$testClass) $testDllDirPath = "$PSScriptRoot\test\CSharp\CodeCracker.Test\bin\Debug\" $testDllFileName = "CodeCracker.Test.CSharp.dll" $testDllFullFileName = "$testDllDirPath$testDllFileName" -$xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" +$xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" if (!(gcm nodemon -ErrorAction Ignore)) { Write-Host -ForegroundColor DarkRed 'Nodemon not found, install it with npm: `npm i -g nodemon`' diff --git a/runTestsVB.ps1 b/runTestsVB.ps1 index 2da22c936..b2d53d619 100644 --- a/runTestsVB.ps1 +++ b/runTestsVB.ps1 @@ -2,7 +2,7 @@ param([String]$testClass) $testDllDirPath = "$PSScriptRoot\test\VisualBasic\CodeCracker.Test\bin\Debug\" $testDllFileName = "CodeCracker.Test.VisualBasic.dll" $testDllFullFileName = "$testDllDirPath$testDllFileName" -$xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe" +$xunitConsole = "$PSScriptRoot\packages\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" if (!(gcm nodemon -ErrorAction Ignore)) { Write-Host -ForegroundColor DarkRed 'Nodemon not found, install it with npm: `npm i -g nodemon`' From 8247e6509729acd2513ab478bc5ac2fee7ce48f8 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 19 Mar 2017 13:09:59 -0300 Subject: [PATCH 136/234] Do not raise a diagnostic for disposables with yield return Fixes #877 --- .../Extensions/CSharpAnalyzerExtensions.cs | 7 ++++++ .../DisposableVariableNotDisposedAnalyzer.cs | 6 +++-- .../DisposableVariableNotDisposedTests.cs | 23 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 50065c3d7..8a248fad1 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -469,6 +469,13 @@ public static IEnumerable OfKind(this IEnumerable node yield return (TNode)node; } + public static IEnumerable OfKind(this IEnumerable nodes, params SyntaxKind[] kinds) where TNode : SyntaxNode + { + foreach (var node in nodes) + if (node.IsAnyKind(kinds)) + yield return (TNode)node; + } + public static IEnumerable OfKind(this IEnumerable nodes, SyntaxKind kind) where TNode : SyntaxNode { foreach (var node in nodes) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index e53f40891..75ed943f4 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -43,7 +43,7 @@ private static void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context) while (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.ConditionalExpression, SyntaxKind.CastExpression)) topSyntaxNode = topSyntaxNode.Parent; - if (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ReturnStatement, SyntaxKind.UsingStatement)) + if (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ReturnStatement, SyntaxKind.UsingStatement, SyntaxKind.YieldReturnStatement)) return; if (topSyntaxNode.Ancestors().Any(i => i.IsAnyKind( @@ -148,10 +148,12 @@ private static bool IsReturned(MethodDeclarationSyntax method, StatementSyntax s body = method.Body; } if (body == null) return true; - var returnExpressions = body.DescendantNodes().OfType().Select(r => r.Expression); var returnTypeSymbol = methodSymbol?.ReturnType; if (returnTypeSymbol == null) return false; if (returnTypeSymbol.SpecialType == SpecialType.System_Void) return false; + var bodyDescendantNodes = body.DescendantNodes().ToList(); + var returnExpressions = bodyDescendantNodes.OfType().Select(r => r.Expression).Union( + bodyDescendantNodes.OfKind(SyntaxKind.YieldReturnStatement).Select(yr => yr.Expression)); var isReturning = returnExpressions.Any(returnExpression => { var returnSymbol = semanticModel.GetSymbolInfo(returnExpression).Symbol; diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index a07c13405..83564c0be 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -123,6 +123,29 @@ public async Task VariableNotDisposableDoesNotCreateDiagnostic() await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task IteratorWithDirectReturnDoesNotCreateDiagnostic() + { + var source = @" +public System.Collections.Generic.IEnumerable Foo() +{ + yield return new System.IO.MemoryStream(); +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task IteratorWithIndirectReturnDoesNotCreateDiagnostic() + { + var source = @" +public System.Collections.Generic.IEnumerable Foo() +{ + var disposable = new System.IO.MemoryStream(); + yield return disposable; +}".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task DisposableVariableCreatesDiagnostic() { From f93c65c84f344218e0e100074c5e314168364f1c Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 19 Mar 2017 13:40:53 -0300 Subject: [PATCH 137/234] Disregard disposables in arrow expressions Fixes #880 --- .../Usage/DisposableVariableNotDisposedAnalyzer.cs | 1 + .../Usage/DisposableVariableNotDisposedTests.cs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index 75ed943f4..2a4b4c32f 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -47,6 +47,7 @@ private static void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context) return; if (topSyntaxNode.Ancestors().Any(i => i.IsAnyKind( + SyntaxKind.ArrowExpressionClause, SyntaxKind.ThisConstructorInitializer, SyntaxKind.BaseConstructorInitializer, SyntaxKind.ObjectCreationExpression))) diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index 83564c0be..d1ad9d3e9 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -123,6 +123,13 @@ public async Task VariableNotDisposableDoesNotCreateDiagnostic() await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task ReturnOnExpressionBodiedMembersDoNotCreateDiagnostic() + { + var source = @"public static System.IO.MemoryStream Foo() => new System.IO.MemoryStream();".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task IteratorWithDirectReturnDoesNotCreateDiagnostic() { From 5c769f3431f3fbd1e867069b87fc1409d6877292 Mon Sep 17 00:00:00 2001 From: sdygert Date: Sun, 19 Mar 2017 13:39:28 -0700 Subject: [PATCH 138/234] Update grammar in TaskNameAsyncAnalyzer.cs #839 --- src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs index d90d22915..6c0f8997c 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs @@ -10,10 +10,10 @@ namespace CodeCracker.CSharp.Style [DiagnosticAnalyzer(LanguageNames.CSharp)] public class TaskNameAsyncAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Async method can be terminating with 'Async' name."; + internal const string Title = "Asynchronous method can be terminated with the 'Async' keyword."; internal const string MessageFormat = "Change method name to {0}"; internal const string Category = SupportedCategories.Style; - const string Description = "Async method can be terminating with 'Async' name."; + const string Description = "Asynchronous method can be terminated with the 'Async' keyword."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.TaskNameAsync.ToDiagnosticId(), @@ -55,4 +55,4 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(diag); } } -} \ No newline at end of file +} From c3402230b1fde51ae52837a27469fc57d4f0509b Mon Sep 17 00:00:00 2001 From: sdygert Date: Sun, 19 Mar 2017 13:50:01 -0700 Subject: [PATCH 139/234] Update grammar in EmptyObjectInitializerAnalyzer.cs #839 --- .../CodeCracker/Style/EmptyObjectInitializerAnalyzer.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/EmptyObjectInitializerAnalyzer.cs b/src/CSharp/CodeCracker/Style/EmptyObjectInitializerAnalyzer.cs index 7597ea48c..1ae23376f 100644 --- a/src/CSharp/CodeCracker/Style/EmptyObjectInitializerAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/EmptyObjectInitializerAnalyzer.cs @@ -12,8 +12,7 @@ public class EmptyObjectInitializerAnalyzer : DiagnosticAnalyzer internal const string Title = "Empty Object Initializer"; internal const string MessageFormat = "{0}"; internal const string Category = SupportedCategories.Style; - const string Description = "An empty object initializer doesn't add any information and only clutter the code.\r\n" - + "If there is no member to initialize, prefer using the standard constructor syntax."; + const string Description = "An object initializer without any arguments can be replaced with the standard constructor syntax."; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.EmptyObjectInitializer.ToDiagnosticId(), @@ -38,9 +37,9 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (objectCreation.Initializer != null && !objectCreation.Initializer.Expressions.Any()) { - var diagnostic = Diagnostic.Create(Rule, objectCreation.Initializer.OpenBraceToken.GetLocation(), "Remove empty object initializer."); + var diagnostic = Diagnostic.Create(Rule, objectCreation.Initializer.OpenBraceToken.GetLocation(), "Remove the empty object initializer."); context.ReportDiagnostic(diagnostic); } } } -} \ No newline at end of file +} From fafd44dc44387d31936c9b8cac50ba20fb54f138 Mon Sep 17 00:00:00 2001 From: sdygert Date: Sun, 19 Mar 2017 13:50:21 -0700 Subject: [PATCH 140/234] Update grammar in EmptyObjectInitializerTests.cs #839 --- .../CodeCracker.Test/Style/EmptyObjectInitializerTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs b/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs index a32dccc61..129824e22 100644 --- a/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs @@ -14,7 +14,7 @@ public async Task EmptyObjectInitializerTriggersFix() var expected = new DiagnosticResult { Id = DiagnosticId.EmptyObjectInitializer.ToDiagnosticId(), - Message = "Remove empty object initializer.", + Message = "Remove the empty object initializer.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 1, 15) } }; @@ -54,4 +54,4 @@ public async Task AbsenceOfObjectInitializerIsIgnored() await VerifyCSharpHasNoDiagnosticsAsync(code); } } -} \ No newline at end of file +} From 6d7ad2139631d24555d23aae321b8e2be210b728 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 19 Mar 2017 22:20:13 -0300 Subject: [PATCH 141/234] Update changelog --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8af91802e..1b460cecb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,15 @@ ## [Unreleased](https://github.com/code-cracker/code-cracker/tree/HEAD) -[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.2...HEAD) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.3...HEAD) -**Closed issues:** +## [v1.0.3](https://github.com/code-cracker/code-cracker/tree/v1.0.3) (2017-03-20) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.2...v1.0.3) + +**Fixed bugs:** +- BUG: CC0022 DisposableVariableNotDisposedAnalyzer: False positive for expression bodied members [\#880](https://github.com/code-cracker/code-cracker/issues/880) +- BUG: CC0022 DisposableVariableNotDisposedAnalyzer: False positive in iterator methods [\#877](https://github.com/code-cracker/code-cracker/issues/877) ## [v1.0.2](https://github.com/code-cracker/code-cracker/tree/v1.0.2) (2017-03-12) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.1...v1.0.2) From 02bbf094a2f92e93e527758b6cd2f5bec4347dc1 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Mon, 20 Mar 2017 18:05:43 +0100 Subject: [PATCH 142/234] Ported analyzer and codefixprovider from https://github.com/ifpanalytics/Ifp.Analyzers/ --- .../CodeCracker.Vsix/CodeCracker.Vsix.csproj | 5 +- src/CSharp/CodeCracker/CodeCracker.csproj | 2 + .../Extensions/CSharpAnalyzerExtensions.cs | 5 + ...placeWithGetterOnlyAutoPropertyAnalyzer.cs | 77 +++++ ...thGetterOnlyAutoPropertyCodeFixProvider.cs | 140 ++++++++ src/Common/CodeCracker.Common/DiagnosticId.cs | 1 + .../Properties/Resources.Designer.cs | 126 ++++--- .../Properties/Resources.resx | 12 + .../CodeCracker.Test/CodeCracker.Test.csproj | 1 + .../ReplaceWithGetterOnlyAutoPropertyTests.cs | 325 ++++++++++++++++++ 10 files changed, 646 insertions(+), 48 deletions(-) create mode 100644 src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs create mode 100644 src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs create mode 100644 test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj index 12f744c47..7dde1ebf3 100644 --- a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj @@ -1,14 +1,13 @@  - + - 15.0 + 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - 15.0 diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 19bb1a9e7..a6d7d52d7 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -67,6 +67,8 @@ + + diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 8a248fad1..0ccb8b5a6 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -17,12 +17,17 @@ public static void RegisterSyntaxNodeAction(this AnalysisCont public static void RegisterCompilationStartAction(this AnalysisContext context, LanguageVersion greaterOrEqualThanLanguageVersion, Action registrationAction) => context.RegisterCompilationStartAction(compilationContext => compilationContext.RunIfCSharpVersionOrGreater(greaterOrEqualThanLanguageVersion, () => registrationAction?.Invoke(compilationContext))); + + public static void RegisterSymbolAction(this AnalysisContext context, LanguageVersion greaterOrEqualThanLanguageVersion, Action registrationAction, params SymbolKind[] symbolKinds) => + context.RegisterSymbolAction(compilationContext => compilationContext.RunIfCSharpVersionOrGreater(greaterOrEqualThanLanguageVersion, () => registrationAction?.Invoke(compilationContext)), symbolKinds); #pragma warning disable RS1012 private static void RunIfCSharpVersionOrGreater(this CompilationStartAnalysisContext context, LanguageVersion greaterOrEqualThanLanguageVersion, Action action) => context.Compilation.RunIfCSharpVersionOrGreater(action, greaterOrEqualThanLanguageVersion); #pragma warning restore RS1012 private static void RunIfCSharpVersionOrGreater(this Compilation compilation, Action action, LanguageVersion greaterOrEqualThanLanguageVersion) => (compilation as CSharpCompilation)?.LanguageVersion.RunIfCSharpVersionGreater(action, greaterOrEqualThanLanguageVersion); + private static void RunIfCSharpVersionOrGreater(this SymbolAnalysisContext context, LanguageVersion greaterOrEqualThanLanguageVersion, Action action) => + context.Compilation.RunIfCSharpVersionOrGreater(action, greaterOrEqualThanLanguageVersion); private static void RunIfCSharpVersionGreater(this LanguageVersion languageVersion, Action action, LanguageVersion greaterOrEqualThanLanguageVersion) { diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs new file mode 100644 index 000000000..b9d16cc4a --- /dev/null +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs @@ -0,0 +1,77 @@ +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeCracker.CSharp.Refactoring +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class ReplaceWithGetterOnlyAutoPropertyAnalyzer : DiagnosticAnalyzer + { + internal const string Category = SupportedCategories.Refactoring; + internal static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.ReplaceWithGetterOnlyAutoPropertyAnalyzer_Title), Resources.ResourceManager, typeof(Resources)); + internal static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.ReplaceWithGetterOnlyAutoPropertyAnalyzer_Description), Resources.ResourceManager, typeof(Resources)); + internal static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.ReplaceWithGetterOnlyAutoPropertyAnalyzer_MessageFormat), Resources.ResourceManager, typeof(Resources)); + + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Title, + MessageFormat, + Category, + DiagnosticSeverity.Hidden, + isEnabledByDefault: true, + description: Description, + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.ReplaceWithGetterOnlyAutoProperty)); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + public override void Initialize(AnalysisContext context) + { + context.RegisterSymbolAction(LanguageVersion.CSharp6, AnalyzeSymbol, SymbolKind.Property); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context) + { + if (context.IsGenerated()) return; + var namedTypeSymbol = (IPropertySymbol)context.Symbol; + var properties = GetPropsWithOnlyGettersAndReadonlyBackingField(namedTypeSymbol, context); + if (properties == null) return; + var diagnostic = Diagnostic.Create(Rule, properties.Item1.Locations[0], properties.Item1.Name); + context.ReportDiagnostic(diagnostic); + } + private static Tuple GetPropsWithOnlyGettersAndReadonlyBackingField(IPropertySymbol propertySymbol, SymbolAnalysisContext context) + { + SemanticModel model = null; + if (!propertySymbol.IsReadOnly || propertySymbol.IsStatic || !propertySymbol.CanBeReferencedByName) return null; + var getMethod = propertySymbol.GetMethod; + if (getMethod == null) return null; + var reference = getMethod.DeclaringSyntaxReferences.FirstOrDefault(); + if (reference == null) return null; + var declaration = reference.GetSyntax(context.CancellationToken) as AccessorDeclarationSyntax; + if (declaration?.Body == null) return null; + var returnNode = declaration.Body.ChildNodes().FirstOrDefault(); + if (returnNode?.Kind() != SyntaxKind.ReturnStatement) return null; + var fieldNode = returnNode.ChildNodes().FirstOrDefault(); + if (fieldNode == null) return null; + if (fieldNode.Kind() == SyntaxKind.SimpleMemberAccessExpression) + fieldNode = (fieldNode as MemberAccessExpressionSyntax).Name; + if (fieldNode.Kind() != SyntaxKind.IdentifierName) return null; + model = model ?? context.Compilation.GetSemanticModel(fieldNode.SyntaxTree); + var symbolInfo = model.GetSymbolInfo(fieldNode).Symbol as IFieldSymbol; + if (symbolInfo != null && + symbolInfo.IsReadOnly && + (symbolInfo.DeclaredAccessibility == Accessibility.Private || symbolInfo.DeclaredAccessibility == Accessibility.NotApplicable) && + symbolInfo.ContainingType == propertySymbol.ContainingType && + symbolInfo.Type.Equals(propertySymbol.Type)) + + return new Tuple(propertySymbol, symbolInfo); + return null; + } + } +} diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs new file mode 100644 index 000000000..c67c076ed --- /dev/null +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs @@ -0,0 +1,140 @@ +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Text; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeCracker.CSharp.Refactoring +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ReplaceWithGetterOnlyAutoPropertyCodeFixProvider)), Shared] + public class ReplaceWithGetterOnlyAutoPropertyCodeFixProvider : CodeFixProvider + { + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId()); + + public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var diagnostic = context.Diagnostics.First(); + var diagnosticSpan = diagnostic.Location.SourceSpan; + + context.RegisterCodeFix( + CodeAction.Create( + title: Resources.ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title, + createChangedDocument: c => ReplaceByGetterOnlyAutoPropertyAsync(context.Document, diagnosticSpan, c), + equivalenceKey: nameof(ReplaceWithGetterOnlyAutoPropertyCodeFixProvider)), + diagnostic); + return Task.FromResult(0); + } + private async static Task ReplaceByGetterOnlyAutoPropertyAsync(Document document, TextSpan propertyDeclarationSpan, CancellationToken cancellationToken) + { + var semanticModel = await document.GetSemanticModelAsync(cancellationToken); + var root = await document.GetSyntaxRootAsync(cancellationToken); + var token = root.FindToken(propertyDeclarationSpan.Start); + var property = token.Parent.AncestorsAndSelf().OfType().First(); + var fieldVariableDeclaratorSyntax = await GetFieldDeclarationSyntaxNodeAsync(property, cancellationToken, semanticModel); + if (fieldVariableDeclaratorSyntax == null) return document; + var fieldReferences = await GetFieldReferencesAsync(fieldVariableDeclaratorSyntax, cancellationToken, semanticModel); + var nodesToUpdate = fieldReferences.Cast().Union(Enumerable.Repeat(property, 1)).Union(Enumerable.Repeat(fieldVariableDeclaratorSyntax, 1)); + var newRoot = FixWithTrackNode(root, property, fieldVariableDeclaratorSyntax, nodesToUpdate); + var resultDocument = document.WithSyntaxRoot(newRoot); + return resultDocument; + } + + private static SyntaxNode FixWithTrackNode(SyntaxNode root, PropertyDeclarationSyntax property, VariableDeclaratorSyntax fieldVariableDeclaratorSyntax, IEnumerable nodesToUpdate) + { + var newRoot = root.TrackNodes(nodesToUpdate); + var fieldReferences = newRoot.GetCurrentNodes(nodesToUpdate.OfType()); + foreach (var identifier in fieldReferences) + { + var newIdentifier = SyntaxFactory.IdentifierName(property.Identifier.Text); + newIdentifier = newIdentifier.WithLeadingTrivia(identifier.GetLeadingTrivia()).WithTrailingTrivia(identifier.GetTrailingTrivia()).WithAdditionalAnnotations(Formatter.Annotation); + newRoot = newRoot.ReplaceNode(identifier, newIdentifier); + } + var prop = newRoot.GetCurrentNode(nodesToUpdate.OfType().Single()); + var fieldInitilization = GetFieldInitialization(fieldVariableDeclaratorSyntax); + var getter = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + var accessorList = SyntaxFactory.AccessorList( + SyntaxFactory.List(new[] { + getter + })); + var newProp = prop.WithAccessorList(accessorList); + if (fieldInitilization != null) + newProp = newProp.WithInitializer(fieldInitilization).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + newProp = newProp.WithLeadingTrivia(prop.GetLeadingTrivia()).WithTrailingTrivia(prop.GetTrailingTrivia()).WithAdditionalAnnotations(Formatter.Annotation); + newRoot = newRoot.ReplaceNode(prop, newProp); + var variableDeclarator = newRoot.GetCurrentNode(nodesToUpdate.OfType().Single()); + var declaration = variableDeclarator.AncestorsAndSelf().OfType().First(); + if (declaration.Variables.Count == 1) + { + var fieldDeclaration = declaration.AncestorsAndSelf().OfType().First(); + newRoot = newRoot.RemoveNode(fieldDeclaration, SyntaxRemoveOptions.KeepUnbalancedDirectives); + } + else + newRoot = newRoot.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepUnbalancedDirectives); + return newRoot; + } + + private static EqualsValueClauseSyntax GetFieldInitialization(VariableDeclaratorSyntax fieldVariableDeclaratorSyntax) + { + var declaration = fieldVariableDeclaratorSyntax.AncestorsAndSelf().OfType().First(); + if (declaration == null) + return null; + var variableWithPotentialInitializer = declaration.Variables.SkipWhile(v => v != fieldVariableDeclaratorSyntax).FirstOrDefault(v => v.Initializer != null); + if (variableWithPotentialInitializer == null) + return null; + var initializer = variableWithPotentialInitializer.Initializer; + return initializer; + } + + private static async Task> GetFieldReferencesAsync(VariableDeclaratorSyntax fieldDeclarationSyntax, CancellationToken cancellationToken, SemanticModel semanticModel) + { + HashSet fieldReferences = null; + var fieldSymbol = semanticModel.GetDeclaredSymbol(fieldDeclarationSyntax); + var declaredInType = fieldSymbol.ContainingType; + foreach (var reference in declaredInType.DeclaringSyntaxReferences) + { + var allNodesOfType = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); + var allFieldReferenceNodes = from n in allNodesOfType.OfType() + where n.Identifier.ValueText == fieldDeclarationSyntax.Identifier.ValueText + select n; + foreach (var fieldReference in allFieldReferenceNodes) + { + var parentExpression = fieldReference.Parent; + if (parentExpression is MemberAccessExpressionSyntax) + parentExpression = parentExpression.Parent; + if (parentExpression is AssignmentExpressionSyntax) + { + var assignmentEx = (AssignmentExpressionSyntax)parentExpression; + if (assignmentEx.Left == fieldReference || assignmentEx.Left == fieldReference.Parent) + (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); + } + } + } + return fieldReferences ?? Enumerable.Empty(); + } + + private static async Task GetFieldDeclarationSyntaxNodeAsync(PropertyDeclarationSyntax propertyDeclaration, CancellationToken cancellationToken, SemanticModel semanticModel) + { + var propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); + var declaredProperty = propertySymbol.GetMethod.DeclaringSyntaxReferences.FirstOrDefault(); + var declaredPropertySyntax = await declaredProperty.GetSyntaxAsync(cancellationToken); + var fieldIdentifier = declaredPropertySyntax.DescendantNodesAndTokens().FirstOrDefault(n => n.IsNode && n.Kind() == SyntaxKind.IdentifierName); + var fieldInfo = semanticModel.GetSymbolInfo(fieldIdentifier.AsNode()); + var fieldDeclaration = fieldInfo.Symbol.DeclaringSyntaxReferences.FirstOrDefault(); + var fieldDeclarationSyntax = await fieldDeclaration.GetSyntaxAsync(); + return fieldDeclarationSyntax as VariableDeclaratorSyntax; + } + } +} diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index e60eb36f8..a0d12446a 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -83,5 +83,6 @@ public enum DiagnosticId UnnecessaryToStringInStringConcatenation = 118, SwitchCaseWithoutDefault = 120, ReadOnlyComplexTypes = 121, + ReplaceWithGetterOnlyAutoProperty=125, } } \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs b/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs index a9cc2ac5f..318839da0 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs +++ b/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -14,12 +14,12 @@ namespace CodeCracker.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -34,7 +34,7 @@ internal Resources() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -48,8 +48,8 @@ internal Resources() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -62,7 +62,7 @@ internal Resources() { } /// - /// Looks up a localized string similar to String interpolation allows for better reading of the resulting string when compared to Console.WriteLine arguments. You should use Console.WriteLine with arguments only when another method is supplying the format string.. + /// Sucht eine lokalisierte Zeichenfolge, die String interpolation allows for better reading of the resulting string when compared to Console.WriteLine arguments. You should use Console.WriteLine with arguments only when another method is supplying the format string. ähnelt. /// public static string ConsoleWriteLineAnalyzer_Description { get { @@ -71,7 +71,7 @@ public static string ConsoleWriteLineAnalyzer_Description { } /// - /// Looks up a localized string similar to Use string interpolation. + /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation ähnelt. /// public static string ConsoleWriteLineAnalyzer_MessageFormat { get { @@ -80,7 +80,7 @@ public static string ConsoleWriteLineAnalyzer_MessageFormat { } /// - /// Looks up a localized string similar to Use string interpolation instead of arguments on Console.WriteLine. + /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation instead of arguments on Console.WriteLine ähnelt. /// public static string ConsoleWriteLineAnalyzer_Title { get { @@ -89,7 +89,7 @@ public static string ConsoleWriteLineAnalyzer_Title { } /// - /// Looks up a localized string similar to Change to string interpolation. + /// Sucht eine lokalisierte Zeichenfolge, die Change to string interpolation ähnelt. /// public static string ConsoleWriteLineCodeFixProvider_Title { get { @@ -98,7 +98,7 @@ public static string ConsoleWriteLineCodeFixProvider_Title { } /// - /// Looks up a localized string similar to An empty catch block suppress all errors and shouldn't be used.\r\nIf the error is expected consider logging it or changing the control flow such that it is explicit.. + /// Sucht eine lokalisierte Zeichenfolge, die An empty catch block suppress all errors and shouldn't be used.\r\nIf the error is expected consider logging it or changing the control flow such that it is explicit. ähnelt. /// public static string EmptyCatchBlockAnalyzer_Description { get { @@ -107,7 +107,7 @@ public static string EmptyCatchBlockAnalyzer_Description { } /// - /// Looks up a localized string similar to Empty Catch Block.. + /// Sucht eine lokalisierte Zeichenfolge, die Empty Catch Block. ähnelt. /// public static string EmptyCatchBlockAnalyzer_Message { get { @@ -116,7 +116,7 @@ public static string EmptyCatchBlockAnalyzer_Message { } /// - /// Looks up a localized string similar to Catch block cannot be empty. + /// Sucht eine lokalisierte Zeichenfolge, die Catch block cannot be empty ähnelt. /// public static string EmptyCatchBlockAnalyzer_Title { get { @@ -125,7 +125,7 @@ public static string EmptyCatchBlockAnalyzer_Title { } /// - /// Looks up a localized string similar to Insert Exception class to Catch. + /// Sucht eine lokalisierte Zeichenfolge, die Insert Exception class to Catch ähnelt. /// public static string EmptyCatchBlockCodeFixProvider_InsertException { get { @@ -134,7 +134,7 @@ public static string EmptyCatchBlockCodeFixProvider_InsertException { } /// - /// Looks up a localized string similar to Remove Empty Catch Block. + /// Sucht eine lokalisierte Zeichenfolge, die Remove Empty Catch Block ähnelt. /// public static string EmptyCatchBlockCodeFixProvider_Remove { get { @@ -143,7 +143,7 @@ public static string EmptyCatchBlockCodeFixProvider_Remove { } /// - /// Looks up a localized string similar to Remove Empty Catch Block and Put a Documentation Link about Try...Catch use. + /// Sucht eine lokalisierte Zeichenfolge, die Remove Empty Catch Block and Put a Documentation Link about Try...Catch use ähnelt. /// public static string EmptyCatchBlockCodeFixProvider_RemoveAndDocumentation { get { @@ -152,7 +152,7 @@ public static string EmptyCatchBlockCodeFixProvider_RemoveAndDocumentation { } /// - /// Looks up a localized string similar to Remove wrapping Try Block. + /// Sucht eine lokalisierte Zeichenfolge, die Remove wrapping Try Block ähnelt. /// public static string EmptyCatchBlockCodeFixProvider_RemoveTry { get { @@ -161,7 +161,7 @@ public static string EmptyCatchBlockCodeFixProvider_RemoveTry { } /// - /// Looks up a localized string similar to Change field type '{0}' accessibility to be as accessible as field '{1}'. + /// Sucht eine lokalisierte Zeichenfolge, die Change field type '{0}' accessibility to be as accessible as field '{1}' ähnelt. /// public static string InconsistentAccessibilityInFieldType_Title { get { @@ -170,7 +170,7 @@ public static string InconsistentAccessibilityInFieldType_Title { } /// - /// Looks up a localized string similar to Change parameter type '{0}' accessibility to be as accessible as indexer 'this[{1}]'. + /// Sucht eine lokalisierte Zeichenfolge, die Change parameter type '{0}' accessibility to be as accessible as indexer 'this[{1}]' ähnelt. /// public static string InconsistentAccessibilityInIndexerParameter_Title { get { @@ -179,7 +179,7 @@ public static string InconsistentAccessibilityInIndexerParameter_Title { } /// - /// Looks up a localized string similar to Change indexer return type '{0}' accessibility to be as accessible as indexer 'this[{1}]'. + /// Sucht eine lokalisierte Zeichenfolge, die Change indexer return type '{0}' accessibility to be as accessible as indexer 'this[{1}]' ähnelt. /// public static string InconsistentAccessibilityInIndexerReturnType_Title { get { @@ -188,7 +188,7 @@ public static string InconsistentAccessibilityInIndexerReturnType_Title { } /// - /// Looks up a localized string similar to Change parameter type '{0}' accessibility to be as accessible as method '{1}'. + /// Sucht eine lokalisierte Zeichenfolge, die Change parameter type '{0}' accessibility to be as accessible as method '{1}' ähnelt. /// public static string InconsistentAccessibilityInMethodParameter_Title { get { @@ -197,7 +197,7 @@ public static string InconsistentAccessibilityInMethodParameter_Title { } /// - /// Looks up a localized string similar to Change return type '{0}' accessibility to be as accessible as method '{1}'. + /// Sucht eine lokalisierte Zeichenfolge, die Change return type '{0}' accessibility to be as accessible as method '{1}' ähnelt. /// public static string InconsistentAccessibilityInMethodReturnType_Title { get { @@ -206,7 +206,7 @@ public static string InconsistentAccessibilityInMethodReturnType_Title { } /// - /// Looks up a localized string similar to Change property type '{0}' accessibility to be as accessible as property '{1}'. + /// Sucht eine lokalisierte Zeichenfolge, die Change property type '{0}' accessibility to be as accessible as property '{1}' ähnelt. /// public static string InconsistentAccessibilityInPropertyType_Title { get { @@ -215,7 +215,7 @@ public static string InconsistentAccessibilityInPropertyType_Title { } /// - /// Looks up a localized string similar to Make method non async. + /// Sucht eine lokalisierte Zeichenfolge, die Make method non async ähnelt. /// public static string MakeMethodNonAsyncCodeFixProvider_Title { get { @@ -224,7 +224,7 @@ public static string MakeMethodNonAsyncCodeFixProvider_Title { } /// - /// Looks up a localized string similar to In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produce code that is easier to refactor.. + /// Sucht eine lokalisierte Zeichenfolge, die In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produce code that is easier to refactor. ähnelt. /// public static string NameOfAnalyzer_Description { get { @@ -233,7 +233,7 @@ public static string NameOfAnalyzer_Description { } /// - /// Looks up a localized string similar to Use 'nameof({0})' instead of specifying the program element name.. + /// Sucht eine lokalisierte Zeichenfolge, die Use 'nameof({0})' instead of specifying the program element name. ähnelt. /// public static string NameOfAnalyzer_MessageFormat { get { @@ -242,7 +242,7 @@ public static string NameOfAnalyzer_MessageFormat { } /// - /// Looks up a localized string similar to Use nameof. + /// Sucht eine lokalisierte Zeichenfolge, die Use nameof ähnelt. /// public static string NameOfAnalyzer_Title { get { @@ -251,7 +251,7 @@ public static string NameOfAnalyzer_Title { } /// - /// Looks up a localized string similar to Use nameof(). + /// Sucht eine lokalisierte Zeichenfolge, die Use nameof() ähnelt. /// public static string NameOfCodeFixProvider_Title { get { @@ -260,7 +260,43 @@ public static string NameOfCodeFixProvider_Title { } /// - /// Looks up a localized string similar to String interpolation allows for better reading of the resulting string when compared to String.Format. You should use String.Format only when another method is supplying the format string.. + /// Sucht eine lokalisierte Zeichenfolge, die Getter only properties with backing read-only field can be converted to getter-only auto-properties. ähnelt. + /// + public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_Description { + get { + return ResourceManager.GetString("ReplaceWithGetterOnlyAutoPropertyAnalyzer_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Property {0} can be converted to an getter-only auto-property. ähnelt. + /// + public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_MessageFormat { + get { + return ResourceManager.GetString("ReplaceWithGetterOnlyAutoPropertyAnalyzer_MessageFormat", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Property can be simplified by using an getter-only auto-property. ähnelt. + /// + public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_Title { + get { + return ResourceManager.GetString("ReplaceWithGetterOnlyAutoPropertyAnalyzer_Title", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Simplify by using an getter-only auto-property ähnelt. + /// + public static string ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title { + get { + return ResourceManager.GetString("ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die String interpolation allows for better reading of the resulting string when compared to String.Format. You should use String.Format only when another method is supplying the format string. ähnelt. /// public static string StringFormatAnalyzer_Description { get { @@ -269,7 +305,7 @@ public static string StringFormatAnalyzer_Description { } /// - /// Looks up a localized string similar to Use string interpolation. + /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation ähnelt. /// public static string StringFormatAnalyzer_MessageFormat { get { @@ -278,7 +314,7 @@ public static string StringFormatAnalyzer_MessageFormat { } /// - /// Looks up a localized string similar to Use string interpolation instead of String.Format. + /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation instead of String.Format ähnelt. /// public static string StringFormatAnalyzer_Title { get { @@ -287,7 +323,7 @@ public static string StringFormatAnalyzer_Title { } /// - /// Looks up a localized string similar to Change to string interpolation. + /// Sucht eine lokalisierte Zeichenfolge, die Change to string interpolation ähnelt. /// public static string StringFormatCodeFixProvider_Title { get { @@ -296,7 +332,7 @@ public static string StringFormatCodeFixProvider_Title { } /// - /// Looks up a localized string similar to Auto properties offer a more concise way of defining a property. If you are using simple getters and setters you are able to simplify your code with autoproperties.. + /// Sucht eine lokalisierte Zeichenfolge, die Auto properties offer a more concise way of defining a property. If you are using simple getters and setters you are able to simplify your code with autoproperties. ähnelt. /// public static string SwitchToAutoPropAnalyzer_Description { get { @@ -305,7 +341,7 @@ public static string SwitchToAutoPropAnalyzer_Description { } /// - /// Looks up a localized string similar to Change {0} to an auto property. + /// Sucht eine lokalisierte Zeichenfolge, die Change {0} to an auto property ähnelt. /// public static string SwitchToAutoPropAnalyzer_MessageFormat { get { @@ -314,7 +350,7 @@ public static string SwitchToAutoPropAnalyzer_MessageFormat { } /// - /// Looks up a localized string similar to Use auto property. + /// Sucht eine lokalisierte Zeichenfolge, die Use auto property ähnelt. /// public static string SwitchToAutoPropAnalyzer_Title { get { @@ -323,7 +359,7 @@ public static string SwitchToAutoPropAnalyzer_Title { } /// - /// Looks up a localized string similar to Change to auto property. + /// Sucht eine lokalisierte Zeichenfolge, die Change to auto property ähnelt. /// public static string SwitchToAutoPropCodeFixProvider_Title { get { @@ -332,7 +368,7 @@ public static string SwitchToAutoPropCodeFixProvider_Title { } /// - /// Looks up a localized string similar to You have missing/unexistent parameters in Xml Docs. + /// Sucht eine lokalisierte Zeichenfolge, die You have missing/unexistent parameters in Xml Docs ähnelt. /// public static string XmlDocumentationAnalyzer_Title { get { @@ -341,7 +377,7 @@ public static string XmlDocumentationAnalyzer_Title { } /// - /// Looks up a localized string similar to Create missing parameters in xml docs. + /// Sucht eine lokalisierte Zeichenfolge, die Create missing parameters in xml docs ähnelt. /// public static string XmlDocumentationCreateMissingParametersCodeFixProvider_Title { get { @@ -350,7 +386,7 @@ public static string XmlDocumentationCreateMissingParametersCodeFixProvider_Titl } /// - /// Looks up a localized string similar to Remove unexistent parameters in xml docs. + /// Sucht eine lokalisierte Zeichenfolge, die Remove unexistent parameters in xml docs ähnelt. /// public static string XmlDocumentationRemoveNonExistentParametersCodeFixProvider_Title { get { diff --git a/src/Common/CodeCracker.Common/Properties/Resources.resx b/src/Common/CodeCracker.Common/Properties/Resources.resx index 1b6e5d917..accb497bd 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.resx +++ b/src/Common/CodeCracker.Common/Properties/Resources.resx @@ -216,4 +216,16 @@ Remove wrapping Try Block + + Getter only properties with backing read-only field can be converted to getter-only auto-properties. + + + Property {0} can be converted to an getter-only auto-property. + + + Property can be simplified by using an getter-only auto-property. + + + Simplify by using an getter-only auto-property + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 1b62b386c..4198a1676 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -135,6 +135,7 @@ + diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs new file mode 100644 index 000000000..ec2ad725b --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs @@ -0,0 +1,325 @@ +using CodeCracker.CSharp.Refactoring; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace CodeCracker.Test.CSharp.Refactoring +{ + public class ReplaceWithGetterOnlyAutoPropertyTests : CodeFixVerifier + { + private static string GetDiagnosticMessage(string propertyName) => $"Property {propertyName} can be converted to an getter-only auto-property."; + + [Fact] + public async Task EmptyCodeBlockPassesWithoutErrors() + { + const string test = @""; + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] + public async Task SimplePropertyGetsTransformed() + { + var test = @" + readonly string _value; + + TypeName(string value) + { + _value=value; + } + + public string Value { get { return _value; } } + ".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = "CC0125", + Message = GetDiagnosticMessage("Value"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 16, 27) + } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + + var fixtest = @" + TypeName(string value) + { + Value = value; + } + + public string Value { get; } + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task SimplePropertyGetsNotTransformedIfLessThanCSharp6() + { + var test = @" + readonly string _value; + + TypeName(string value) + { + _value=value; + } + + public string Value { get { return _value; } } + ".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(test, LanguageVersion.CSharp5); + } + + [Fact] + public async Task FieldInitializerIsPreserved() + { + var test = @" + readonly string value, value2 = ""InitValue""; + + TypeName(string value) + { + this.value=value; + } + + public string Value { get { return this.value; } } + ".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("Value"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 16, 27) + } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + + var fixtest = @" + readonly string value2 = ""InitValue""; + + TypeName(string value) + { + this.Value = value; + } + + public string Value { get; } = ""InitValue""; + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task MultiplePropertiesPerClassGetTranformed() + { + var test = @" + readonly string value, value2=""InitValue""; + + TypeName(string value) + { + this.value=value; + this.value2=value; + } + + public string Value { get { return this.value; } } + public string Value2 { get { return this.value2; } } + ".WrapInCSharpClass(); + + var expected1 = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("Value"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 17, 27) + } + }; + var expected2 = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("Value2"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 18, 27) + } + }; + + await VerifyCSharpDiagnosticAsync(test, new DiagnosticResult[] { expected1, expected2 }); + + var fixtest = @" + TypeName(string value) + { + this.Value = value; + this.Value2 = value; + } + + public string Value { get; } = ""InitValue""; + public string Value2 { get; } = ""InitValue""; + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task MultiplePropertiesPerClassWithFieldInitilizerAndUnusedFieldsGetTranformed() + { + var test = @" + readonly string value, value2, value3=""InitValue""; + + TypeName(string value) + { + this.value=value; + this.value2=value; + } + + public string Value { get { return this.value; } } + public string Value2 { get { return this.value2; } } + ".WrapInCSharpClass(); + var expected1 = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("Value"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 17, 27) + } + }; + var expected2 = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("Value2"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 18, 27) + } + }; + + await VerifyCSharpDiagnosticAsync(test, new DiagnosticResult[] { expected1, expected2 }); + + var fixtest = @" + readonly string value3=""InitValue""; + + TypeName(string value) + { + this.Value = value; + this.Value2 = value; + } + + public string Value { get; } = ""InitValue""; + public string Value2 { get; } = ""InitValue""; + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task TypeOfPropertyMustFitTypeOfBackingField() + { + var test = @" + readonly IList value, value2; + + TypeName(IEnumerable value) + { + this.value=value.ToList(); + this.value2=value.ToList(); + } + + public IEnumerable Value { get { return this.value; } } + public IList Value2 { get { return this.value2; } } + ".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("Value2"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 18, 34) + } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + + var fixtest = @" + readonly IList value; + + TypeName(IEnumerable value) + { + this.value=value.ToList(); + this.Value2 = value.ToList(); + } + + public IEnumerable Value { get { return this.value; } } + public IList Value2 { get; } + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task ExplicitPropertyImplementationsAreIgnored() + { + const string test = @" + namespace ConsoleApplication1 + { + interface ITestInterface + { + string Property { get; } + } + class TestClass2: ITestInterface + { + readonly string _Property; + + string ITestInterface.Property + { + get + { + return _Property; + } + } + } + }"; + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] + public async Task SeveralInitializerAreAssignedProperly() + { + var test = @" + readonly int a = 0, x, y = 1, z = 2; + + public int X + { + get + { + return x; + } + } + ".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), + Message = GetDiagnosticMessage("X"), + Severity = DiagnosticSeverity.Hidden, + Locations = + new[] { + new DiagnosticResultLocation("Test0.cs", 11, 24) + } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + + var fixtest = @" + readonly int a = 0, y = 1, z = 2; + + public int X { get; } = 1; + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + } +} From 07c9a00e0810a522d9d1ff43f4ea92fc7fbb8a1a Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 22 Mar 2017 10:13:13 +0100 Subject: [PATCH 143/234] Changed Renaming logic and added some renaming tests. --- ...thGetterOnlyAutoPropertyCodeFixProvider.cs | 30 +-- .../ReplaceWithGetterOnlyAutoPropertyTests.cs | 219 ++++++++++++++++-- 2 files changed, 215 insertions(+), 34 deletions(-) diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs index c67c076ed..5503dbe8f 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs @@ -34,7 +34,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) title: Resources.ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title, createChangedDocument: c => ReplaceByGetterOnlyAutoPropertyAsync(context.Document, diagnosticSpan, c), equivalenceKey: nameof(ReplaceWithGetterOnlyAutoPropertyCodeFixProvider)), - diagnostic); + diagnostic); return Task.FromResult(0); } private async static Task ReplaceByGetterOnlyAutoPropertyAsync(Document document, TextSpan propertyDeclarationSpan, CancellationToken cancellationToken) @@ -55,12 +55,13 @@ private async static Task ReplaceByGetterOnlyAutoPropertyAsync(Documen private static SyntaxNode FixWithTrackNode(SyntaxNode root, PropertyDeclarationSyntax property, VariableDeclaratorSyntax fieldVariableDeclaratorSyntax, IEnumerable nodesToUpdate) { var newRoot = root.TrackNodes(nodesToUpdate); - var fieldReferences = newRoot.GetCurrentNodes(nodesToUpdate.OfType()); + var fieldReferences = nodesToUpdate.OfType(); foreach (var identifier in fieldReferences) { - var newIdentifier = SyntaxFactory.IdentifierName(property.Identifier.Text); - newIdentifier = newIdentifier.WithLeadingTrivia(identifier.GetLeadingTrivia()).WithTrailingTrivia(identifier.GetTrailingTrivia()).WithAdditionalAnnotations(Formatter.Annotation); - newRoot = newRoot.ReplaceNode(identifier, newIdentifier); + var trackedIdentifierNode = newRoot.GetCurrentNode(identifier); + var newIdentifierExpression = SyntaxFactory.IdentifierName(property.Identifier.Text); + newIdentifierExpression = newIdentifierExpression.WithLeadingTrivia(trackedIdentifierNode.GetLeadingTrivia()).WithTrailingTrivia(trackedIdentifierNode.GetTrailingTrivia()).WithAdditionalAnnotations(Formatter.Annotation); + newRoot = newRoot.ReplaceNode(trackedIdentifierNode, newIdentifierExpression); } var prop = newRoot.GetCurrentNode(nodesToUpdate.OfType().Single()); var fieldInitilization = GetFieldInitialization(fieldVariableDeclaratorSyntax); @@ -101,25 +102,18 @@ private static EqualsValueClauseSyntax GetFieldInitialization(VariableDeclarator private static async Task> GetFieldReferencesAsync(VariableDeclaratorSyntax fieldDeclarationSyntax, CancellationToken cancellationToken, SemanticModel semanticModel) { HashSet fieldReferences = null; - var fieldSymbol = semanticModel.GetDeclaredSymbol(fieldDeclarationSyntax); + var fieldSymbol = semanticModel.GetDeclaredSymbol(fieldDeclarationSyntax, cancellationToken); var declaredInType = fieldSymbol.ContainingType; foreach (var reference in declaredInType.DeclaringSyntaxReferences) { - var allNodesOfType = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); - var allFieldReferenceNodes = from n in allNodesOfType.OfType() - where n.Identifier.ValueText == fieldDeclarationSyntax.Identifier.ValueText + var allNodes = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); + var allFieldReferenceNodes = from n in allNodes.OfType() + let nodeSymbolInfo = semanticModel.GetSymbolInfo(n, cancellationToken) + where object.Equals(nodeSymbolInfo.Symbol, fieldSymbol) select n; foreach (var fieldReference in allFieldReferenceNodes) { - var parentExpression = fieldReference.Parent; - if (parentExpression is MemberAccessExpressionSyntax) - parentExpression = parentExpression.Parent; - if (parentExpression is AssignmentExpressionSyntax) - { - var assignmentEx = (AssignmentExpressionSyntax)parentExpression; - if (assignmentEx.Left == fieldReference || assignmentEx.Left == fieldReference.Parent) - (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); - } + (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); } } return fieldReferences ?? Enumerable.Empty(); diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs index ec2ad725b..825a083e0 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs @@ -1,10 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Xunit; @@ -301,25 +297,216 @@ public int X } } ".WrapInCSharpClass(); - var expected = new DiagnosticResult + var fixtest = @" + readonly int a = 0, y = 1, z = 2; + + public int X { get; } = 1; + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task FieldNameIsRenamedInClass() + { + var test = @" + readonly int _X; + + public TypeName(int x) { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("X"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 11, 24) - } - }; + _X=x; + _X=_X*2; + Console.Write(_X); + } - await VerifyCSharpDiagnosticAsync(test, expected); + protected void M() => Console.Write(_X); + public int X + { + get + { + return _X; + } + } + ".WrapInCSharpClass(); var fixtest = @" - readonly int a = 0, y = 1, z = 2; + public TypeName(int x) + { + X=x; + X=X*2; + Console.Write(X); + } - public int X { get; } = 1; + protected void M() => Console.Write(X); + + public int X { get; } + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task ShadowedFieldNameIsNotRenamedInClass() + { + var test = @" + readonly int _X; + + public TypeName(int x) + { + _X=x; + } + + protected void M() + { + string _X=""; + Console.Write(_X); + } + + public int X + { + get + { + return _X; + } + } + ".WrapInCSharpClass(); + var fixtest = @" + public TypeName(int x) + { + X=x; + } + + protected void M() + { + string _X=""; + Console.Write(_X); + } + + public int X { get; } + ".WrapInCSharpClass(); + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task FieldAccessInInnerClassIsRenamed() + { + var test = @" + readonly int _A; + + public TypeName(int a) + { + _A=a; + } + + class InnerClass { + InnerClass(TypeName outterObject) + { + Console.Write(outterObject._A); + } + } + public int A + { + get + { + return _A; + } + } + ".WrapInCSharpClass(); + var fixtest = @" + public TypeName(int a) + { + A=a; + } + + class InnerClass { + InnerClass(TypeName outterObject) + { + Console.Write(outterObject.A); + } + } + public int A { get; } ".WrapInCSharpClass(); await VerifyCSharpFixAsync(test, fixtest); } + + [Fact] + public async Task FieldWithSameNameInOtherClassIsNotRenamed() + { + var test = @" + using System; + namespace App { + public class C1 + { + readonly int _A; + + public C1(int a) + { + _A=a; + } + + public int A + { + get + { + return _A; + } + } + } + public class C2 + { + readonly int _A; + } + }"; + var fixtest = @" + using System; + namespace App { + public class C1 + { + + public C1(int a) + { + A=a; + } + + public int A { get; } + } + public class C2 + { + readonly int _A; + } + }"; + await VerifyCSharpFixAsync(test, fixtest); + } + + [Fact] + public async Task RenamingOfFieldAccessCanIntroduceNameClashesCaughtByCompilerWarningCS1717() + { + var test = @" + readonly int _A; + + public TypeName(int A) + { + _A=A; + } + + public int A + { + get + { + return _A; + } + } + ".WrapInCSharpClass(); + var fixtest = @" + public TypeName(int A) + { + A=A; + } + + public int A { get; } + ".WrapInCSharpClass(); + // "A=A;" causes new compiler warning CS1717: Assignment made to same variable; did you mean to assign something else? + // The fix would be to transform the expression to this.A=A; + // Maybe using Microsoft.CodeAnalysis.Rename.Renamer.RenameSymbolAsync() for the renaming is the able to fix this. + await VerifyCSharpFixAsync(oldSource: test, newSource: fixtest, allowNewCompilerDiagnostics: true); + } } } From c1bdfbda9fd4578b4b2613a4fd5269a7e74d4eb0 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 22 Mar 2017 10:57:30 +0100 Subject: [PATCH 144/234] Prepare Pull Request: Reverted some VS2015 compatibility changes. --- src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj index 7dde1ebf3..12f744c47 100644 --- a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj @@ -1,13 +1,14 @@  - + - 14.0 + 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + 15.0 From 5c4007b3ce70e48cd3df2f1d7b219624d58de410 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 22 Mar 2017 11:00:01 +0100 Subject: [PATCH 145/234] Cleanup before PullRequest --- .../Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs | 3 --- .../ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs | 2 -- src/Common/CodeCracker.Common/DiagnosticId.cs | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs index b9d16cc4a..59291bf23 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs @@ -4,11 +4,8 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace CodeCracker.CSharp.Refactoring { diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs index 5503dbe8f..e467153ed 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs @@ -6,12 +6,10 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Text; -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index a0d12446a..28feee0f8 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -83,6 +83,6 @@ public enum DiagnosticId UnnecessaryToStringInStringConcatenation = 118, SwitchCaseWithoutDefault = 120, ReadOnlyComplexTypes = 121, - ReplaceWithGetterOnlyAutoProperty=125, + ReplaceWithGetterOnlyAutoProperty = 125, } } \ No newline at end of file From b4d2856fc88dd38366f1ad41311f11890d08f7ed Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 22 Mar 2017 11:07:20 +0100 Subject: [PATCH 146/234] Clean up of analyzer. --- .../ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs index 59291bf23..cc8b4ef13 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyAnalyzer.cs @@ -28,6 +28,7 @@ public class ReplaceWithGetterOnlyAutoPropertyAnalyzer : DiagnosticAnalyzer helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.ReplaceWithGetterOnlyAutoProperty)); public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + public override void Initialize(AnalysisContext context) { context.RegisterSymbolAction(LanguageVersion.CSharp6, AnalyzeSymbol, SymbolKind.Property); @@ -39,12 +40,11 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) var namedTypeSymbol = (IPropertySymbol)context.Symbol; var properties = GetPropsWithOnlyGettersAndReadonlyBackingField(namedTypeSymbol, context); if (properties == null) return; - var diagnostic = Diagnostic.Create(Rule, properties.Item1.Locations[0], properties.Item1.Name); + var diagnostic = Diagnostic.Create(Rule, properties.Locations[0], properties.Name); context.ReportDiagnostic(diagnostic); } - private static Tuple GetPropsWithOnlyGettersAndReadonlyBackingField(IPropertySymbol propertySymbol, SymbolAnalysisContext context) + private static ISymbol GetPropsWithOnlyGettersAndReadonlyBackingField(IPropertySymbol propertySymbol, SymbolAnalysisContext context) { - SemanticModel model = null; if (!propertySymbol.IsReadOnly || propertySymbol.IsStatic || !propertySymbol.CanBeReferencedByName) return null; var getMethod = propertySymbol.GetMethod; if (getMethod == null) return null; @@ -59,7 +59,7 @@ private static Tuple GetPropsWithOnlyGettersAndReadonlyBa if (fieldNode.Kind() == SyntaxKind.SimpleMemberAccessExpression) fieldNode = (fieldNode as MemberAccessExpressionSyntax).Name; if (fieldNode.Kind() != SyntaxKind.IdentifierName) return null; - model = model ?? context.Compilation.GetSemanticModel(fieldNode.SyntaxTree); + var model = context.Compilation.GetSemanticModel(fieldNode.SyntaxTree); var symbolInfo = model.GetSymbolInfo(fieldNode).Symbol as IFieldSymbol; if (symbolInfo != null && symbolInfo.IsReadOnly && @@ -67,7 +67,7 @@ private static Tuple GetPropsWithOnlyGettersAndReadonlyBa symbolInfo.ContainingType == propertySymbol.ContainingType && symbolInfo.Type.Equals(propertySymbol.Type)) - return new Tuple(propertySymbol, symbolInfo); + return propertySymbol; return null; } } From fa20c951cf11e561a64c1d141a8a95614f53f7ca Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Mon, 27 Mar 2017 13:58:44 +0200 Subject: [PATCH 147/234] Bugfix: semanticModel.GetSymbolInfo might raise ArgumentException (Node not found in tree) for certain symbols. --- .../ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs index e467153ed..80db718c6 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs @@ -106,6 +106,7 @@ private static async Task> GetFieldReferencesA { var allNodes = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); var allFieldReferenceNodes = from n in allNodes.OfType() + where n.Identifier.Text == fieldSymbol.Name let nodeSymbolInfo = semanticModel.GetSymbolInfo(n, cancellationToken) where object.Equals(nodeSymbolInfo.Symbol, fieldSymbol) select n; From 308f450277867ad479105b1b7b2c8bb4f2589c90 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 29 Mar 2017 13:52:12 +0200 Subject: [PATCH 148/234] Bugfix: Partial classes in different documents cause ArgumentException. --- ...thGetterOnlyAutoPropertyCodeFixProvider.cs | 20 ++-- .../ReplaceWithGetterOnlyAutoPropertyTests.cs | 94 ++++++++++++++++++- 2 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs index 80db718c6..d22626bae 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs @@ -102,18 +102,16 @@ private static async Task> GetFieldReferencesA HashSet fieldReferences = null; var fieldSymbol = semanticModel.GetDeclaredSymbol(fieldDeclarationSyntax, cancellationToken); var declaredInType = fieldSymbol.ContainingType; - foreach (var reference in declaredInType.DeclaringSyntaxReferences) + var reference = declaredInType.DeclaringSyntaxReferences[0]; + var allNodes = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); + var allFieldReferenceNodes = from n in allNodes.OfType() + where n.Identifier.Text == fieldSymbol.Name + let nodeSymbolInfo = semanticModel.GetSymbolInfo(n, cancellationToken) + where object.Equals(nodeSymbolInfo.Symbol, fieldSymbol) + select n; + foreach (var fieldReference in allFieldReferenceNodes) { - var allNodes = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); - var allFieldReferenceNodes = from n in allNodes.OfType() - where n.Identifier.Text == fieldSymbol.Name - let nodeSymbolInfo = semanticModel.GetSymbolInfo(n, cancellationToken) - where object.Equals(nodeSymbolInfo.Symbol, fieldSymbol) - select n; - foreach (var fieldReference in allFieldReferenceNodes) - { - (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); - } + (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); } return fieldReferences ?? Enumerable.Empty(); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs index 825a083e0..d7ffc711d 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs @@ -508,5 +508,97 @@ public TypeName(int A) // Maybe using Microsoft.CodeAnalysis.Rename.Renamer.RenameSymbolAsync() for the renaming is the able to fix this. await VerifyCSharpFixAsync(oldSource: test, newSource: fixtest, allowNewCompilerDiagnostics: true); } + + [Fact] + public async Task FieldReferencesInPartialClassesGetNotRenamedAndCasueCompilerErrorCS0103() + { + const string test = @" + namespace A + { + using System; + public partial class A1 + { + readonly int _I; + public A1(int i) + { + _I = i; + } + public int I { get { return _I; } } + } + public partial class A1 + { + public void Print() => Console.Write(_I); + } + }"; + const string fixtest = @" + namespace A + { + using System; + public partial class A1 + { + public A1(int i) + { + I = i; + } + public int I { get; } + } + public partial class A1 + { + public void Print() => Console.Write(_I); + } + }"; + //Console.Write(_I); causes CS0103 The name '_I' does not exist in the current context + await VerifyCSharpFixAsync(oldSource: test, newSource: fixtest, allowNewCompilerDiagnostics: true); + } + + [Fact] + public async Task FieldReferencesInPartialClassesInDifferentDocumentsGetNotRenamedAndCauseCompilerErrorCS0103() + { + const string testPart1 = @" + namespace A + { + public partial class A1 + { + readonly int _I; + public A1(int i) + { + _I = i; + } + public int I { get { return _I; } } + } + }"; + const string testPart2 = @" + namespace A + { + using System; + public partial class A1 + { + public void Print() => Console.Write(_I); + } + }"; + const string fixtestPart1 = @" + namespace A + { + public partial class A1 + { + public A1(int i) + { + I = i; + } + public int I { get; } + } + }"; + const string fixtestPart2 = @" + namespace A + { + using System; + public partial class A1 + { + public void Print() => Console.Write(_I); + } + }"; + //Console.Write(_I); causes CS0103 The name '_I' does not exist in the current context + await VerifyCSharpFixAllAsync(oldSources: new string[] { testPart1, testPart2 }, newSources: new string[] { fixtestPart1, fixtestPart2 }, allowNewCompilerDiagnostics: true); + } } -} +} \ No newline at end of file From e6d44e596af62dcb89fa1b6fe10b2162e14b8b37 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Thu, 27 Apr 2017 15:54:10 +0200 Subject: [PATCH 149/234] Added CoalesceExpression to the list of possible parents in topSyntaxNode discovery. --- .../DisposableVariableNotDisposedAnalyzer.cs | 2 +- .../DisposableVariableNotDisposedTests.cs | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index 2a4b4c32f..3ed958b5f 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -40,7 +40,7 @@ private static void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context) var originalNode = objectCreation; SyntaxNode topSyntaxNode = originalNode; - while (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.ConditionalExpression, SyntaxKind.CastExpression)) + while (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.ConditionalExpression, SyntaxKind.CastExpression, SyntaxKind.CoalesceExpression)) topSyntaxNode = topSyntaxNode.Parent; if (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ReturnStatement, SyntaxKind.UsingStatement, SyntaxKind.YieldReturnStatement)) diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index d1ad9d3e9..e2f2a9fd9 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -1577,5 +1577,26 @@ void Bar() }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } + + [Fact] + public async Task IgnoreWhenAssignedToFieldByNullCoalescingOperator() + { + const string source = @" +using System.IO; +public class Test : IDisposable +{ + private IDisposable _stream; + + public void Update() + { + _stream = _stream ?? new MemoryStream(); + } + + public void Dispose() + { + _stream.Dispose(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); } -} \ No newline at end of file +}} \ No newline at end of file From e74608cf2fd991ac3b353fb0d44671dd37e1e596 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Thu, 27 Apr 2017 16:12:09 +0200 Subject: [PATCH 150/234] Code formating. --- .../Usage/DisposableVariableNotDisposedTests.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index e2f2a9fd9..cb1437596 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -1578,10 +1578,10 @@ void Bar() await VerifyCSharpHasNoDiagnosticsAsync(source); } - [Fact] - public async Task IgnoreWhenAssignedToFieldByNullCoalescingOperator() - { - const string source = @" + [Fact] + public async Task IgnoreWhenAssignedToFieldByNullCoalescingOperator() + { + const string source = @" using System.IO; public class Test : IDisposable { @@ -1597,6 +1597,7 @@ public void Dispose() _stream.Dispose(); } }"; - await VerifyCSharpHasNoDiagnosticsAsync(source); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } -}} \ No newline at end of file +} \ No newline at end of file From 41aa788fc2752e83318edc600ccc73f11dadf37f Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Thu, 27 Apr 2017 18:05:34 +0200 Subject: [PATCH 151/234] Added support for Winforms property default value definition methods. --- .../RemovePrivateMethodNeverUsedAnalyzer.cs | 35 +++++++++ ...emovePrivateMethodNeverUsedAnalyzerTest.cs | 76 +++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs index 25bd20246..26b80458c 100644 --- a/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/RemovePrivateMethodNeverUsedAnalyzer.cs @@ -44,6 +44,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) if (IsMethodUsed(methodDeclaration, context.SemanticModel)) return; if (IsMainMethodEntryPoint(methodDeclaration, context.SemanticModel)) return; if (methodDeclaration.Modifiers.Any(SyntaxKind.ExternKeyword)) return; + if (IsWinformsPropertyDefaultValueDefinitionMethod(methodDeclaration, context.SemanticModel)) return; var props = new Dictionary { { "identifier", methodDeclaration.Identifier.Text } }.ToImmutableDictionary(); var diagnostic = Diagnostic.Create(Rule, methodDeclaration.GetLocation(), props); context.ReportDiagnostic(diagnostic); @@ -125,5 +126,39 @@ private static bool IsMainMethodEntryPoint(MethodDeclarationSyntax methodTarget, if (!parameterType.OriginalDefinition.ToString().Equals("String[]", StringComparison.OrdinalIgnoreCase)) return false; return true; } + + // see https://msdn.microsoft.com/en-us/library/53b8022e(v=vs.110).aspx + private static bool IsWinformsPropertyDefaultValueDefinitionMethod(MethodDeclarationSyntax methodTarget, SemanticModel semanticModel) + { + var propertyName = GetPropertyNameForWinformDefaultValueMethods(methodTarget, semanticModel); + if (string.IsNullOrWhiteSpace(propertyName)) return false; + if (!ExistsProperty(propertyName, methodTarget, semanticModel)) return false; + return true; + } + + private static string GetPropertyNameForWinformDefaultValueMethods(MethodDeclarationSyntax methodTarget, SemanticModel semanticModel) => + GetPropertyNameForMethodWithSignature(methodTarget, semanticModel, "Reset", "Void") ?? + GetPropertyNameForMethodWithSignature(methodTarget, semanticModel, "ShouldSerialize", "Boolean"); + + private static string GetPropertyNameForMethodWithSignature(MethodDeclarationSyntax methodTarget, SemanticModel semanticModel, string startsWith, string returnType) + { + var methodName = methodTarget.Identifier.Text; + if (methodName.StartsWith(startsWith)) + if (methodTarget.ParameterList.Parameters.Count == 0) + { + var returnTypeInfo = semanticModel.GetTypeInfo(methodTarget.ReturnType).Type; + if (returnTypeInfo.Name.Equals(returnType, StringComparison.OrdinalIgnoreCase)) + return methodName.Substring(startsWith.Length); ; + } + return null; + } + + private static bool ExistsProperty(string propertyName, SyntaxNode nodeInType, SemanticModel semanticModel) + { + var typeDeclaration = nodeInType.AncestorsAndSelf().OfType().FirstOrDefault(); + if (typeDeclaration == null) return false; + var propertyDeclarations = typeDeclaration.DescendantNodes().OfType(); + return propertyDeclarations.Any(pd => pd.Identifier.Text == propertyName); + } } } diff --git a/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs b/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs index abc0c6e97..3c5383c1e 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs @@ -1,4 +1,5 @@ using CodeCracker.CSharp.Usage; +using Microsoft.CodeAnalysis; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -408,5 +409,80 @@ bool System.IEquatable.Equals(Foo other) }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } + + // see https://msdn.microsoft.com/en-us/library/53b8022e(v=vs.110).aspx + [Fact] + public async void WinFormsPropertyDefaultValueDefinitionMethodsShouldBeIgnored() + { + var source = @" +public int PropertyXXX { + get; + set; +} + +private bool ShouldSerializePropertyXXX() => true; + +private void ResetPropertyXXX() { }; +".WrapInCSharpClass(); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + private static DiagnosticResult CreateDiagnosticResult(int line, int column) => + new DiagnosticResult + { + Id = DiagnosticId.RemovePrivateMethodNeverUsed.ToDiagnosticId(), + Locations = new DiagnosticResultLocation[] { new DiagnosticResultLocation("Test0.cs", line, column) }, + Message = RemovePrivateMethodNeverUsedAnalyzer.Message, + Severity = DiagnosticSeverity.Info, + }; + + [Fact] + public async void WinFormsPropertyDefaultValueDefinitionMethodsMustHaveCorrectSignature() + { + var source = @" +public int Property1 { get; set; } +public int Property2 { get; set; } +public int Property3 { get; set; } + +private int ShouldSerializeProperty1() => 1; +private bool ShouldSerializeProperty2(int i) => true; +private void ShouldSerializeProperty3() { }; + +private bool ResetProperty1() => true; +private void ResetProperty2(int i) { }; +".WrapInCSharpClass(); + var result1 = CreateDiagnosticResult(13, 1); + var result2 = CreateDiagnosticResult(14, 1); + var result3 = CreateDiagnosticResult(15, 1); + var result4 = CreateDiagnosticResult(17, 1); + var result5 = CreateDiagnosticResult(18, 1); + await VerifyCSharpDiagnosticAsync(source, new DiagnosticResult[] { result1, result2, result3, result4, result5 }); + } + + [Fact] + public async void WinFormsPropertyDefaultValueDefinitionMethodsMustHaveCorrespondingProperty() + { + var source = @" +private bool ShouldSerializePropertyXXX() => true; + +private void ResetPropertyXXX() { }; +".WrapInCSharpClass(); + var result1 = CreateDiagnosticResult(9, 1); + var result2 = CreateDiagnosticResult(11, 1); + await VerifyCSharpDiagnosticAsync(source, new DiagnosticResult[] { result1, result2 }); + } + + [Fact] + public async void WinFormsPropertyDefaultValueDefinitionMethodsMustHaveASuffix() + { + var source = @" +private bool ShouldSerialize() => true; + +private void ResetProperty() { }; +".WrapInCSharpClass(); + var result1 = CreateDiagnosticResult(9, 1); + var result2 = CreateDiagnosticResult(11, 1); + await VerifyCSharpDiagnosticAsync(source, new DiagnosticResult[] { result1, result2 }); + } } } \ No newline at end of file From d8cc1f75f2b75dcb10d5f4a4082da4b918501e74 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Thu, 27 Apr 2017 15:54:10 +0200 Subject: [PATCH 152/234] Added CoalesceExpression to the list of possible parents in topSyntaxNode discovery. --- .../DisposableVariableNotDisposedAnalyzer.cs | 2 +- .../DisposableVariableNotDisposedTests.cs | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index 2a4b4c32f..3ed958b5f 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -40,7 +40,7 @@ private static void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context) var originalNode = objectCreation; SyntaxNode topSyntaxNode = originalNode; - while (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.ConditionalExpression, SyntaxKind.CastExpression)) + while (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.ConditionalExpression, SyntaxKind.CastExpression, SyntaxKind.CoalesceExpression)) topSyntaxNode = topSyntaxNode.Parent; if (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.ReturnStatement, SyntaxKind.UsingStatement, SyntaxKind.YieldReturnStatement)) diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index d1ad9d3e9..e2f2a9fd9 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -1577,5 +1577,26 @@ void Bar() }"; await VerifyCSharpHasNoDiagnosticsAsync(source); } + + [Fact] + public async Task IgnoreWhenAssignedToFieldByNullCoalescingOperator() + { + const string source = @" +using System.IO; +public class Test : IDisposable +{ + private IDisposable _stream; + + public void Update() + { + _stream = _stream ?? new MemoryStream(); + } + + public void Dispose() + { + _stream.Dispose(); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); } -} \ No newline at end of file +}} \ No newline at end of file From 98270b530444432601a68d937297ed47f4f52a04 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Thu, 27 Apr 2017 16:12:09 +0200 Subject: [PATCH 153/234] Code formating. --- .../Usage/DisposableVariableNotDisposedTests.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index e2f2a9fd9..cb1437596 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -1578,10 +1578,10 @@ void Bar() await VerifyCSharpHasNoDiagnosticsAsync(source); } - [Fact] - public async Task IgnoreWhenAssignedToFieldByNullCoalescingOperator() - { - const string source = @" + [Fact] + public async Task IgnoreWhenAssignedToFieldByNullCoalescingOperator() + { + const string source = @" using System.IO; public class Test : IDisposable { @@ -1597,6 +1597,7 @@ public void Dispose() _stream.Dispose(); } }"; - await VerifyCSharpHasNoDiagnosticsAsync(source); + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } -}} \ No newline at end of file +} \ No newline at end of file From 871d40f53d43ba7891c427349d6ae21722025b5a Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 19:38:39 -0300 Subject: [PATCH 154/234] Create a single dll for the nupkg Using ilmerge, we are merging the C# and VB dlls with the common dll, which generates a simpler experience for the user. --- .gitignore | 1 + .nuget/packages.config | 1 + build.ps1 | 13 ++- build.targets.ps1 | 99 ++++++++++++++----- src/CSharp/CodeCracker/CodeCracker.nuspec | 2 +- src/CodeCracker.nuspec | 30 ------ .../CodeCracker/CodeCracker.nuspec | 2 +- 7 files changed, 93 insertions(+), 55 deletions(-) delete mode 100644 src/CodeCracker.nuspec diff --git a/.gitignore b/.gitignore index 3da239e30..b5c6a38ac 100644 --- a/.gitignore +++ b/.gitignore @@ -192,3 +192,4 @@ ModelManifest.xml log/ .vs nuget.exe +*.nupkg diff --git a/.nuget/packages.config b/.nuget/packages.config index 5e0ac7672..964028c5c 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -2,4 +2,5 @@ + diff --git a/build.ps1 b/build.ps1 index d1a072785..95d279b16 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,4 +1,6 @@ $ErrorActionPreference = "Stop" +$tempDir = Join-Path "$([System.IO.Path]::GetTempPath())" "CodeCracker" +if (!(Test-Path $tempDir)) { mkdir $tempDir | Out-Null } # functions: function IsNugetVersion3OrAbove($theNugetExe) { @@ -47,7 +49,7 @@ function Download-Nuget { } function Import-Psake { - $psakeModule = "$PSScriptRoot\packages\psake.4.5.0\tools\psake.psm1" + $psakeModule = "$PSScriptRoot\packages\psake.4.6.0\tools\psake.psm1" if ((Test-Path $psakeModule) -ne $true) { Write-Host "Restoring $PSScriptRoot\.nuget with $script:nugetExe" . "$script:nugetExe" restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot @@ -55,12 +57,21 @@ function Import-Psake { Import-Module $psakeModule -force } +function Import-ILMerge { + $ilmergeExe = "$PSScriptRoot\packages\ilmerge.2.14.1208\tools\ILMerge.exe" + if ((Test-Path $ilmergeExe) -ne $true) { + Write-Host "Restoring $PSScriptRoot\.nuget with $script:nugetExe" + . "$script:nugetExe" restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot + } +} + # statements: $localNuget = "$PSScriptRoot\.nuget\nuget.exe" $nugetExe = "" Get-Nuget Import-Psake +Import-ILMerge if ($MyInvocation.UnboundArguments.Count -ne 0) { . $PSScriptRoot\psake.ps1 -taskList ($MyInvocation.UnboundArguments -join " ") } diff --git a/build.targets.ps1 b/build.targets.ps1 index d5c0cc057..253bf1955 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -10,24 +10,33 @@ Properties { $buildNumber = [Convert]::ToInt32($env:APPVEYOR_BUILD_NUMBER).ToString("0000") $nuspecPathCS = "$rootDir\src\CSharp\CodeCracker\CodeCracker.nuspec" $nuspecPathVB = "$rootDir\src\VisualBasic\CodeCracker\CodeCracker.nuspec" - $nuspecPathJoint = "$rootDir\src\CodeCracker.nuspec" $nugetExe = "$packagesDir\NuGet.CommandLine.3.3.0\tools\NuGet.exe" $nupkgPathCS = "$rootDir\src\CSharp\CodeCracker.CSharp.{0}.nupkg" $nupkgPathVB = "$rootDir\src\VisualBasic\CodeCracker.VisualBasic.{0}.nupkg" - $nupkgPathJoint = "$rootDir\CodeCracker.{0}.nupkg" $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" $openCoverExe = "$packagesDir\OpenCover.4.6.519\tools\OpenCover.Console.exe" + $dllCS = "CodeCracker.CSharp.dll" + $dllVB = "CodeCracker.VisualBasic.dll" + $dllCommon = "CodeCracker.Common.dll" $testDllCS = "CodeCracker.Test.CSharp.dll" $testDllVB = "CodeCracker.Test.VisualBasic.dll" $testDirCS = "$testDir\CSharp\CodeCracker.Test\bin\Release" $testDirVB = "$testDir\VisualBasic\CodeCracker.Test\bin\Release" + $projectDirVB = "$srcDir\VisualBasic\CodeCracker" + $projectFileVB = "$projectDirVB\CodeCracker.vbproj" + $releaseDirVB = "$projectDirVB\bin\Release" + $projectDirCS = "$srcDir\CSharp\CodeCracker" + $projectFileCS = "$projectDirCS\CodeCracker.csproj" + $releaseDirCS = "$projectDirCS\bin\Release" $logDir = "$rootDir\log" $outputXml = "$logDir\CodeCoverageResults.xml" $reportGeneratorExe = "$packagesDir\ReportGenerator.2.5.6\tools\ReportGenerator.exe" $coverageReportDir = "$logDir\codecoverage\" $coverallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" + $ilmergeExe = "$packagesDir\ilmerge.2.14.1208\tools\ILMerge.exe" $isRelease = $isAppVeyor -and (($env:APPVEYOR_REPO_BRANCH -eq "release") -or ($env:APPVEYOR_REPO_TAG -eq "true")) $isPullRequest = $env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null + $tempDir = Join-Path "$([System.IO.Path]::GetTempPath())" "CodeCracker" } FormatTaskName (("-"*25) + "[{0}]" + ("-"*25)) @@ -49,14 +58,16 @@ Task Build-CS -depends Prepare-Build, Build-Only-CS Task Build-VB -depends Prepare-Build, Build-Only-VB Task Build-Only -depends Build-Only-CS, Build-Only-VB -Task Build-Only-CS { +Task Build-Only-CS -depends Build-MSBuild-CS, ILMerge-CS +Task Build-MSBuild-CS { if ($isAppVeyor) { Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } } else { Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } } } -Task Build-Only-VB { +Task Build-Only-VB -depends Build-MSBuild-VB, ILMerge-VB +Task Build-MSBuild-VB { if ($isAppVeyor) { Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } } else { @@ -64,6 +75,49 @@ Task Build-Only-VB { } } +Task ILMerge-VB { ILMerge $releaseDirVB $dllVB $projectFileVB $projectDirVB } +Task ILMerge-CS { ILMerge $releaseDirCS $dllCS $projectFileCS $projectDirCS } + +function ILMerge($releaseDir, $dll, $projectFile, $projectDir) { + Write-Host "IL Merge:" + $mergedDir = $tempDir + if (!(Test-Path $mergedDir)) { mkdir "$mergedDir" } + $inputDll = "$releaseDir\$dll" + $inputDllCommon = "$releaseDir\$dllCommon" + $pdbCommon = Change-Extension $inputDllCommon "pdb" + if (Test-Path $inputDllCommon) { + if ((ls $inputDllCommon).LastWriteTime -gt (ls $inputDll).LastWriteTime) { + # common is newer, but no changes on main dll + Write-Host "Common dll is newer than $inputDll, stopping IL merge." + return + } + } else { + # no common dll, can't merge + Write-Host "Can't find common dll, stopping IL merge." + return + } + $mergedDll = "$mergedDir\$dll" + [xml]$proj = cat $projectFile + $libs = @() + foreach ($ref in $proj.Project.ItemGroup.Reference.HintPath) { + $dir += [System.IO.Path]::GetDirectoryName("$projectDir\$ref") + $libs += "/lib:`"$([System.IO.Path]::GetDirectoryName("$projectDir\$ref"))`" " + } + Exec { . $ilmergeExe $libs /out:"$mergedDll" "$inputDll" "$inputDllCommon" } + $releaseMergedDir = "$releaseDir\merged" + if (!(Test-Path $releaseMergedDir)) { mkdir $releaseMergedDir | Out-Null } + cp $mergedDll "$releaseMergedDir\" -Force + Write-Host " $dll -> $releaseMergedDir\$dll" + $mergedPdb = Change-Extension $mergedDll "pdb" + cp $mergedPdb "$releaseMergedDir\" -Force + $pdb = (ls $mergedPdb).Name + Write-Host " $pdb -> $releaseMergedDir\$pdb" +} + +function Change-Extension ($filename, $extension) { + Join-Path "$([System.IO.Path]::GetDirectoryName($filename))" "$([System.IO.Path]::GetFileNameWithoutExtension($filename)).$extension" +} + Task Clean { Exec { msbuild $solutionFileCS /t:Clean /v:quiet } Exec { msbuild $solutionFileVB /t:Clean /v:quiet } @@ -99,10 +153,7 @@ Task Test-No-Coverage-CSharp { RunTest "$testDirCS\$testDllCS" } -Task Update-Nuspec -precondition { return $isAppVeyor -and ($isRelease -ne $true) } -depends Update-Nuspec-Joint -Task Update-Nuspec-Joint -precondition { return $isAppVeyor -and ($isRelease -ne $true) } -depends Update-Nuspec-CSharp, Update-Nuspec-VB { - UpdateNuspec $nuspecPathJoint "joint package" -} +Task Update-Nuspec -precondition { return $isAppVeyor -and ($isRelease -ne $true) } -depends Update-Nuspec-CSharp, Update-Nuspec-VB Task Update-Nuspec-CSharp -precondition { return $isAppVeyor -and ($isRelease -ne $true) } { UpdateNuspec $nuspecPathCS "C#" } @@ -110,31 +161,35 @@ Task Update-Nuspec-VB -precondition { return $isAppVeyor -and ($isRelease -ne $t UpdateNuspec $nuspecPathVB "VB" } -Task Pack-Nuget -precondition { return $isAppVeyor } -depends Pack-Nuget-Joint -Task Pack-Nuget-Joint -precondition { return $isAppVeyor } -depends Pack-Nuget-Csharp, Pack-Nuget-VB { - #we won't be publishing the common package anymore - #PackNuget "Joint package" "$rootDir" $nuspecPathJoint $nupkgPathJoint -} +Task Pack-Nuget -precondition { return $isAppVeyor } -depends Pack-Nuget-Csharp, Pack-Nuget-VB Task Pack-Nuget-CSharp -precondition { return $isAppVeyor } { PackNuget "C#" "$rootDir\src\CSharp" $nuspecPathCS $nupkgPathCS } Task Pack-Nuget-VB -precondition { return $isAppVeyor } { PackNuget "VB" "$rootDir\src\VisualBasic" $nuspecPathVB $nupkgPathVB } +Task Pack-Nuget-Force -depends Pack-Nuget-Csharp-Force, Pack-Nuget-VB-Force +Task Pack-Nuget-Csharp-Force { + PackNuget "C#" "$rootDir\src\CSharp" $nuspecPathCS $nupkgPathCS +} +Task Pack-Nuget-VB-Force { + PackNuget "VB" "$rootDir\src\VisualBasic" $nuspecPathVB $nupkgPathVB +} Task Echo { echo echo } function PackNuget($language, $dir, $nuspecFile, $nupkgFile) { Write-Host "Packing nuget for $language..." - [xml]$xml = cat $nuspecFile + [xml]$xml = cat "$nuspecFile" $nupkgFile = $nupkgFile -f $xml.package.metadata.version - Write-Host "Nupkg path is $nupkgFile" - . $nugetExe pack $nuspecFile -OutputDirectory $dir - ls $nupkgFile - Write-Host "Nuget packed for $language!" - Write-Host "Pushing nuget artifact for $language..." - appveyor PushArtifact $nupkgFile - Write-Host "Nupkg pushed for $language!" + . $nugetExe pack "$nuspecFile" -OutputDirectory "$dir" + $nuspecFileName = (ls $nuspecFile).Name + Write-Host " $nuspecFileName ($language/$($xml.package.metadata.version)) -> $nupkgFile" + if ($isAppVeyor) { + Write-Host "Pushing nuget artifact for $language..." + appveyor PushArtifact $nupkgFile + Write-Host "Nupkg pushed for $language!" + } } function UpdateNuspec($nuspecPath, $language) { @@ -223,4 +278,4 @@ function RunTestWithCoverage($fullTestDllPaths) { Write-Host -ForegroundColor DarkBlue "Uploading coverage report to Coveralls.io" Exec { . $coverallsNetExe --opencover $outputXml --full-sources } } -} +} \ No newline at end of file diff --git a/src/CSharp/CodeCracker/CodeCracker.nuspec b/src/CSharp/CodeCracker/CodeCracker.nuspec index fdfc1e815..91e3f5c70 100644 --- a/src/CSharp/CodeCracker/CodeCracker.nuspec +++ b/src/CSharp/CodeCracker/CodeCracker.nuspec @@ -22,7 +22,7 @@ This is a community project, free and open source. Everyone is invited to contri true - + diff --git a/src/CodeCracker.nuspec b/src/CodeCracker.nuspec deleted file mode 100644 index f5113b83b..000000000 --- a/src/CodeCracker.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - codecracker - 1.1.0 - CodeCracker for C# and VB - giggio,elemarjr,carloscds - giggio,elemarjr,carloscds - https://github.com/code-cracker/code-cracker/blob/master/LICENSE.txt - http://code-cracker.github.io/ - https://avatars1.githubusercontent.com/u/9695920?v=3&s=200 - true - A analyzer library for C# and VB that uses Roslyn to produce refactorings, code analysis, and other niceties. - -You probably don't want this package directly, search for the C# or Visual Basic specific packages (codecracker.CSharp and codecracker.VisualBasic). This will install both. - -This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. - See https://github.com/code-cracker/code-cracker/blob/master/CHANGELOG.md - Copyright CodeCracker 2014-2016 - roslyn, analyzers - - - - - - - - - - diff --git a/src/VisualBasic/CodeCracker/CodeCracker.nuspec b/src/VisualBasic/CodeCracker/CodeCracker.nuspec index 326c5ccb4..8c35dc85b 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.nuspec +++ b/src/VisualBasic/CodeCracker/CodeCracker.nuspec @@ -21,7 +21,7 @@ This is a community project, free and open source. Everyone is invited to contri - + From d37dbd240d893574d35c1f1fe322d1742aa5d961 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 19:44:52 -0300 Subject: [PATCH 155/234] Update dependencies --- .nuget/packages.config | 4 +- build.targets.ps1 | 3 +- psake.ps1 | 4 +- src/CSharp/CodeCracker/CodeCracker.csproj | 50 ++++++++----------- src/CSharp/CodeCracker/packages.config | 16 +++--- .../CodeCracker.Common.csproj | 28 +++++------ src/Common/CodeCracker.Common/packages.config | 12 ++--- .../CodeCracker/CodeCracker.vbproj | 38 ++++++-------- src/VisualBasic/CodeCracker/packages.config | 16 +++--- .../CodeCracker.Test/CodeCracker.Test.csproj | 44 +++++++--------- test/CSharp/CodeCracker.Test/packages.config | 24 ++++++--- .../CodeCracker.Test.Common.csproj | 45 ++++++++--------- .../CodeCracker.Test.Common/packages.config | 28 +++++++---- .../CodeCracker.Test/CodeCracker.Test.vbproj | 44 +++++++--------- .../CodeCracker.Test/packages.config | 24 ++++++--- 15 files changed, 188 insertions(+), 192 deletions(-) diff --git a/.nuget/packages.config b/.nuget/packages.config index 964028c5c..9707f7736 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/build.targets.ps1 b/build.targets.ps1 index 253bf1955..f5be72100 100644 --- a/build.targets.ps1 +++ b/build.targets.ps1 @@ -10,7 +10,8 @@ Properties { $buildNumber = [Convert]::ToInt32($env:APPVEYOR_BUILD_NUMBER).ToString("0000") $nuspecPathCS = "$rootDir\src\CSharp\CodeCracker\CodeCracker.nuspec" $nuspecPathVB = "$rootDir\src\VisualBasic\CodeCracker\CodeCracker.nuspec" - $nugetExe = "$packagesDir\NuGet.CommandLine.3.3.0\tools\NuGet.exe" + $nugetPackagesExe = "$packagesDir\NuGet.CommandLine.4.1.0\tools\NuGet.exe" + $nugetExe = if (Test-Path $nugetPackagesExe) { $nugetPackagesExe } else { 'nuget' } $nupkgPathCS = "$rootDir\src\CSharp\CodeCracker.CSharp.{0}.nupkg" $nupkgPathVB = "$rootDir\src\VisualBasic\CodeCracker.VisualBasic.{0}.nupkg" $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" diff --git a/psake.ps1 b/psake.ps1 index de6e34a2d..ce647902b 100644 --- a/psake.ps1 +++ b/psake.ps1 @@ -1,3 +1,3 @@ -Import-Module $PSScriptRoot\packages\psake.4.5.0\tools\psake.psm1 -force -Invoke-Expression("Invoke-psake -framework '4.5.2' build.targets.ps1 " + $MyInvocation.UnboundArguments -join " ") +Import-Module $PSScriptRoot\packages\psake.4.6.0\tools\psake.psm1 -force +Invoke-Expression("Invoke-psake -framework '4.5.2' $PSScriptRoot\build.targets.ps1 " + $MyInvocation.UnboundArguments -join " ") exit !($psake.build_success) \ No newline at end of file diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index a6d7d52d7..ea63f7981 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -222,37 +222,26 @@ - - {753d4757-fcba-43ba-b1be-89201acda192} - CodeCracker.Common - + + + + - - - - - - - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.CSharp.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.CSharp.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - - ..\..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - False + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll @@ -274,11 +263,16 @@ ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll False - - ..\..\..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll - False + + ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll + + + {753d4757-fcba-43ba-b1be-89201acda192} + CodeCracker.Common + + diff --git a/src/CSharp/CodeCracker/packages.config b/src/CSharp/CodeCracker/packages.config index d1bbcab2c..fcde436eb 100644 --- a/src/CSharp/CodeCracker/packages.config +++ b/src/CSharp/CodeCracker/packages.config @@ -1,12 +1,12 @@  - - - - - - + + + + + + - - + + \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index 3426e7d12..f20344f73 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -70,23 +70,20 @@ - - - - + + + + - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - - ..\..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - False + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll @@ -108,9 +105,8 @@ ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll False - - ..\..\..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll - False + + ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll diff --git a/src/Common/CodeCracker.Common/packages.config b/src/Common/CodeCracker.Common/packages.config index d8681f9ca..847a13861 100644 --- a/src/Common/CodeCracker.Common/packages.config +++ b/src/Common/CodeCracker.Common/packages.config @@ -1,10 +1,10 @@  - - - - + + + + - - + + \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index e2deff9b9..02045debc 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -162,31 +162,26 @@ - - - - + + + + - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.VisualBasic.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.VisualBasic.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - False + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - - ..\..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - False + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll @@ -208,9 +203,8 @@ ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll False - - ..\..\..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll - False + + ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll diff --git a/src/VisualBasic/CodeCracker/packages.config b/src/VisualBasic/CodeCracker/packages.config index 20b3df7df..bc11241d0 100644 --- a/src/VisualBasic/CodeCracker/packages.config +++ b/src/VisualBasic/CodeCracker/packages.config @@ -1,12 +1,12 @@  - - - - - - + + + + + + - - + + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 4198a1676..c45a93ec6 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -46,32 +46,27 @@ ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.Core.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - ..\..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll True @@ -95,9 +90,8 @@ True - - ..\..\..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll - True + + ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll @@ -213,7 +207,7 @@ CodeCracker.Common - {FF1097FB-A890-461B-979E-064697891B96} + {ff1097fb-a890-461b-979e-064697891b96} CodeCracker @@ -232,10 +226,10 @@ - - - - + + + + diff --git a/test/CSharp/CodeCracker.Test/packages.config b/test/CSharp/CodeCracker.Test/packages.config index e6e8b042c..22638264b 100644 --- a/test/CSharp/CodeCracker.Test/packages.config +++ b/test/CSharp/CodeCracker.Test/packages.config @@ -1,16 +1,24 @@  - + - - - - - + + + + + - - + + + + + + + + + + diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index fb0650aee..905792f36 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -41,33 +41,33 @@ ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.Core.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.0.0\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.0.0\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - ..\..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll True @@ -91,9 +91,8 @@ True - - ..\..\..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll - True + + ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll @@ -130,10 +129,10 @@ - - - - + + + + diff --git a/test/Common/CodeCracker.Test.Common/packages.config b/test/Common/CodeCracker.Test.Common/packages.config index b75a21670..c24c4bdc2 100644 --- a/test/Common/CodeCracker.Test.Common/packages.config +++ b/test/Common/CodeCracker.Test.Common/packages.config @@ -1,21 +1,29 @@  - + - - - - - - - + + + + + + + - - + + + + + + + + + + diff --git a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj index 77000d42d..a0ead244c 100644 --- a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj +++ b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj @@ -60,32 +60,27 @@ ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.Core.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.0.0\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.0.0\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll - True + + ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - ..\..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll True @@ -108,9 +103,8 @@ ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll True - - ..\..\..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll - True + + ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll @@ -222,10 +216,10 @@ - - - - + + + + @@ -241,4 +235,4 @@ --> - + \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/packages.config b/test/VisualBasic/CodeCracker.Test/packages.config index 8742f779c..4e3b70206 100644 --- a/test/VisualBasic/CodeCracker.Test/packages.config +++ b/test/VisualBasic/CodeCracker.Test/packages.config @@ -1,16 +1,24 @@  - + - - - - - + + + + + - - + + + + + + + + + + From ae3513041ad8e7cabba002ab60cfdba907c11775 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 19:53:51 -0300 Subject: [PATCH 156/234] Move build.targets.ps1 to default.ps1 to ease psake use Now we don't need to go through build.ps1 for eveything anymore, we can use psake directly as default.ps1 is the default file name for psake. --- CodeCracker.sln | 7 +++---- build.ps1 | 2 +- build.targets.ps1 => default.ps1 | 0 psake.ps1 | 3 --- 4 files changed, 4 insertions(+), 8 deletions(-) rename build.targets.ps1 => default.ps1 (100%) delete mode 100644 psake.ps1 diff --git a/CodeCracker.sln b/CodeCracker.sln index 8061066fb..64406cda0 100644 --- a/CodeCracker.sln +++ b/CodeCracker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" EndProject @@ -42,8 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{234973E7 ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - build.targets.ps1 = build.targets.ps1 - psake.ps1 = psake.ps1 + default.ps1 = default.ps1 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6E93-4D2D-B6F0-141B977AFC9F}" diff --git a/build.ps1 b/build.ps1 index 95d279b16..821027472 100644 --- a/build.ps1 +++ b/build.ps1 @@ -73,7 +73,7 @@ Get-Nuget Import-Psake Import-ILMerge if ($MyInvocation.UnboundArguments.Count -ne 0) { - . $PSScriptRoot\psake.ps1 -taskList ($MyInvocation.UnboundArguments -join " ") + Invoke-Expression("Invoke-psake -framework '4.5.2' $PSScriptRoot\default.ps1 -taskList " + $MyInvocation.UnboundArguments -join " ") } else { . $PSScriptRoot\build.ps1 Build diff --git a/build.targets.ps1 b/default.ps1 similarity index 100% rename from build.targets.ps1 rename to default.ps1 diff --git a/psake.ps1 b/psake.ps1 deleted file mode 100644 index ce647902b..000000000 --- a/psake.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -Import-Module $PSScriptRoot\packages\psake.4.6.0\tools\psake.psm1 -force -Invoke-Expression("Invoke-psake -framework '4.5.2' $PSScriptRoot\build.targets.ps1 " + $MyInvocation.UnboundArguments -join " ") -exit !($psake.build_success) \ No newline at end of file From 163f6bfca19085a65b95a01180c8d357b01a3fd8 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 20:03:15 -0300 Subject: [PATCH 157/234] Adjust sln files to the new psake structure --- CodeCracker.2015.sln | 5 ++--- CodeCracker.CSharp.2015.sln | 7 +++---- CodeCracker.CSharp.sln | 7 +++---- CodeCracker.VisualBasic.2015.sln | 5 ++--- CodeCracker.VisualBasic.sln | 7 +++---- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/CodeCracker.2015.sln b/CodeCracker.2015.sln index 729d7ca60..61766491e 100644 --- a/CodeCracker.2015.sln +++ b/CodeCracker.2015.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" EndProject @@ -42,8 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{234973E7 ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - build.targets.ps1 = build.targets.ps1 - psake.ps1 = psake.ps1 + default.ps1 = default.ps1 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6E93-4D2D-B6F0-141B977AFC9F}" diff --git a/CodeCracker.CSharp.2015.sln b/CodeCracker.CSharp.2015.sln index 0600d9a27..f1ddbefd2 100644 --- a/CodeCracker.CSharp.2015.sln +++ b/CodeCracker.CSharp.2015.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F5240AD-2B4E-48A4-B9FC-7D19DACEF2CD}" ProjectSection(SolutionItems) = preProject @@ -11,7 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F5240 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker", "src\CSharp\CodeCracker\CodeCracker.csproj", "{FF1097FB-A890-461B-979E-064697891B96}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.2015.Vsix", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{6BAC4057-7239-485E-A04B-02E687A83BAA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{6BAC4057-7239-485E-A04B-02E687A83BAA}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test", "test\CSharp\CodeCracker.Test\CodeCracker.Test.csproj", "{F7843158-046E-4B22-95D7-CAC7BB01283D}" EndProject @@ -36,8 +36,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{40545653 ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - build.targets.ps1 = build.targets.ps1 - psake.ps1 = psake.ps1 + default.ps1 = default.ps1 EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" diff --git a/CodeCracker.CSharp.sln b/CodeCracker.CSharp.sln index 2f52cf033..e075a10f0 100644 --- a/CodeCracker.CSharp.sln +++ b/CodeCracker.CSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F5240AD-2B4E-48A4-B9FC-7D19DACEF2CD}" ProjectSection(SolutionItems) = preProject @@ -36,8 +36,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{40545653 ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - build.targets.ps1 = build.targets.ps1 - psake.ps1 = psake.ps1 + default.ps1 = default.ps1 EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" diff --git a/CodeCracker.VisualBasic.2015.sln b/CodeCracker.VisualBasic.2015.sln index 9d3b4ba56..cec5830dd 100644 --- a/CodeCracker.VisualBasic.2015.sln +++ b/CodeCracker.VisualBasic.2015.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" EndProject @@ -24,8 +24,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D1591C8E ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - build.targets.ps1 = build.targets.ps1 - psake.ps1 = psake.ps1 + default.ps1 = default.ps1 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{22D6C608-E7F1-4236-BB07-BE5F97A4C810}" diff --git a/CodeCracker.VisualBasic.sln b/CodeCracker.VisualBasic.sln index 6b903192a..b338754d2 100644 --- a/CodeCracker.VisualBasic.sln +++ b/CodeCracker.VisualBasic.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" EndProject @@ -24,8 +24,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D1591C8E ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - build.targets.ps1 = build.targets.ps1 - psake.ps1 = psake.ps1 + default.ps1 = default.ps1 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{22D6C608-E7F1-4236-BB07-BE5F97A4C810}" From 143c6861fd0c3858503066c5ba94b593807eda43 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 20:08:46 -0300 Subject: [PATCH 158/234] Remove vs 2015 solutions from psake file --- default.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.ps1 b/default.ps1 index f5be72100..d524aad28 100644 --- a/default.ps1 +++ b/default.ps1 @@ -5,7 +5,7 @@ Properties { $srcDir = "$rootDir\src" $testDir = "$rootDir\test" $isAppVeyor = $env:APPVEYOR -eq $true - $slns = ls "$rootDir\*.sln" + $slns = ls "$rootDir\*.sln" | ? { ! $_.Name.Contains('.2015.') } $packagesDir = "$rootDir\packages" $buildNumber = [Convert]::ToInt32($env:APPVEYOR_BUILD_NUMBER).ToString("0000") $nuspecPathCS = "$rootDir\src\CSharp\CodeCracker\CodeCracker.nuspec" From 6af54565725cae759e8b6469053ee3631d6f3ee0 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 20:27:06 -0300 Subject: [PATCH 159/234] Be more specific about nuget restore --- default.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.ps1 b/default.ps1 index d524aad28..a36f5fad6 100644 --- a/default.ps1 +++ b/default.ps1 @@ -205,7 +205,7 @@ function UpdateNuspec($nuspecPath, $language) { function RestorePkgs($sln) { Write-Host "Restoring $sln..." -ForegroundColor Green Retry { - . $nugetExe restore $sln + . $nugetExe restore "$sln" -MSBuildVersion 14 -NonInteractive -ConfigFile "$rootDir\nuget.config" if ($LASTEXITCODE) { throw "Nuget restore for $sln failed." } } } From 1e3e459407ac2661f634112b872325e29c31cd65 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Fri, 23 Jun 2017 02:08:26 +0200 Subject: [PATCH 160/234] Fix CC0014 casting rule bugs Closes #911 --- .../Style/TernaryOperatorCodeFixProvider.cs | 31 ++--------- .../Style/TernaryOperatorTests.cs | 55 +++++++++++++++++++ 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 8444c0705..b36fa9584 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -222,21 +222,16 @@ private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionS if (!elseType.HasImplicitNumericConversion(ifType) && !IsEnumAndZero(ifType, elseExpression) && !IsEnumAndZero(elseType, ifExpression) - && (!isNullable && !ifType.CanBeAssignedTo(elseType) || !elseType.CanBeAssignedTo(ifType))) - trueExpression = CastToBaseType(ifExpression, ifType, elseType, trueExpression); + && (!isNullable && !ifType.CanBeAssignedTo(elseType) || !elseType.CanBeAssignedTo(ifType)) + && ifType != ifConvertedType) + trueExpression = CastToConvertedType(ifExpression, ifConvertedType); } private static bool IsEnumAndZero(ITypeSymbol type, ExpressionSyntax expression) => type?.BaseType?.SpecialType == SpecialType.System_Enum && expression?.ToString() == "0"; - private static ExpressionSyntax CastToBaseType(ExpressionSyntax ifExpression, ITypeSymbol ifType, ITypeSymbol elseType, ExpressionSyntax trueExpression) - { - var commonBaseType = ifType.GetCommonBaseType(elseType); - if (commonBaseType.Equals(ifType)) return trueExpression; - if (commonBaseType != null) - trueExpression = SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(commonBaseType.Name).WithAdditionalAnnotations(Simplifier.Annotation), ifExpression); - return trueExpression; - } + private static ExpressionSyntax CastToConvertedType(ExpressionSyntax ifExpression, ITypeSymbol ifConvertedType) + => SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(ifConvertedType.ToString()).WithAdditionalAnnotations(Simplifier.Annotation), ifExpression); private static bool CanBeAssignedTo(this ITypeSymbol type, ITypeSymbol possibleBaseType) { @@ -252,21 +247,5 @@ private static bool CanBeAssignedTo(this ITypeSymbol type, ITypeSymbol possibleB } return false; } - - private static ITypeSymbol GetCommonBaseType(this ITypeSymbol type, ITypeSymbol otherType) - { - var baseType = type; - while (baseType != null) - { - var otherBaseType = otherType; - while (otherBaseType != null) - { - if (baseType.Equals(otherBaseType)) return baseType; - otherBaseType = otherBaseType.BaseType; - } - baseType = baseType.BaseType; - } - return null; - } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index c9c86f91c..ccfc31761 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -396,6 +396,23 @@ public void Foo() }".WrapInCSharpClass(); await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentToAnInterfaceVariableAFittingCastIsInserted() + { + var source = @" + System.Collections.Generic.IEnumerable e= null; + if (true) + e = new int[10]; + else + e = new System.Collections.Generic.List(); + ".WrapInCSharpMethod(); + var fixtest = @" + System.Collections.Generic.IEnumerable e= null; + e = true ? (System.Collections.Generic.IEnumerable)new int[10] : new System.Collections.Generic.List(); + ".WrapInCSharpMethod(); + await VerifyCSharpFixAsync(source, fixtest); + } } public class TernaryOperatorWithReturnTests : CodeFixVerifier @@ -1327,5 +1344,43 @@ public Object Foo() }".WrapInCSharpClass(); await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenReturnTypeIsAnInterfaceAFittingCastIsInserted() + { + var source = @" + IComparable GetComparable() + { + if (true) + return 1; + else + return ""1""; + }".WrapInCSharpClass(); + var fixtest = @" + IComparable GetComparable() + { + return true?(IComparable)1 : ""1""; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithReturnTypeIsExplicitConvertable() + { + var source = @" + double GetNumber() + { + if (true) + return 1; + else + return 1.1; + }".WrapInCSharpClass(); + var fixtest = @" + double GetNumber() + { + return true?(double)1:1.1; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From bc88e5dc9ecec941224f5fc4a83af5875601f42f Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 21:10:18 -0300 Subject: [PATCH 161/234] Update .gitigore from master --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3da239e30..b5c6a38ac 100644 --- a/.gitignore +++ b/.gitignore @@ -192,3 +192,4 @@ ModelManifest.xml log/ .vs nuget.exe +*.nupkg From 4595fbe1696845b21f952f14c68ca19c6aa13168 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Fri, 23 Jun 2017 02:08:26 +0200 Subject: [PATCH 162/234] Fix CC0014 casting rule bugs Closes #911 --- .../Style/TernaryOperatorCodeFixProvider.cs | 31 +- .../Style/TernaryOperatorTests.cs | 659 ++++++++++++++++++ 2 files changed, 664 insertions(+), 26 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 97ebd2e3f..3c8c8a9f1 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -138,21 +138,16 @@ private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionS if (!elseType.HasImplicitNumericConversion(ifType) && !IsEnumAndZero(ifType, elseExpression) && !IsEnumAndZero(elseType, ifExpression) - && (!isNullable && !ifType.CanBeAssignedTo(elseType) || !elseType.CanBeAssignedTo(ifType))) - trueExpression = CastToBaseType(ifExpression, ifType, elseType, trueExpression); + && (!isNullable && !ifType.CanBeAssignedTo(elseType) || !elseType.CanBeAssignedTo(ifType)) + && ifType != ifConvertedType) + trueExpression = CastToConvertedType(ifExpression, ifConvertedType); } private static bool IsEnumAndZero(ITypeSymbol type, ExpressionSyntax expression) => type?.BaseType?.SpecialType == SpecialType.System_Enum && expression?.ToString() == "0"; - private static ExpressionSyntax CastToBaseType(ExpressionSyntax ifExpression, ITypeSymbol ifType, ITypeSymbol elseType, ExpressionSyntax trueExpression) - { - var commonBaseType = ifType.GetCommonBaseType(elseType); - if (commonBaseType.Equals(ifType)) return trueExpression; - if (commonBaseType != null) - trueExpression = SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(commonBaseType.Name).WithAdditionalAnnotations(Simplifier.Annotation), ifExpression); - return trueExpression; - } + private static ExpressionSyntax CastToConvertedType(ExpressionSyntax ifExpression, ITypeSymbol ifConvertedType) + => SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(ifConvertedType.ToString()).WithAdditionalAnnotations(Simplifier.Annotation), ifExpression); private static bool CanBeAssignedTo(this ITypeSymbol type, ITypeSymbol possibleBaseType) { @@ -168,21 +163,5 @@ private static bool CanBeAssignedTo(this ITypeSymbol type, ITypeSymbol possibleB } return false; } - - private static ITypeSymbol GetCommonBaseType(this ITypeSymbol type, ITypeSymbol otherType) - { - var baseType = type; - while (baseType != null) - { - var otherBaseType = otherType; - while (otherBaseType != null) - { - if (baseType.Equals(otherBaseType)) return baseType; - otherBaseType = otherBaseType.BaseType; - } - baseType = baseType.BaseType; - } - return null; - } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs index 68d90f96d..ccfc31761 100644 --- a/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TernaryOperatorTests.cs @@ -334,6 +334,85 @@ public static void Foo() "; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultChangeToTernaryFixGetsArgsApplied() + { + var source = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + if (something) + { + a = Method(1); + } + else + { + a = Method(2); + } + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + a = Method(something?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentOfMethodResultWithComplexArgumentEvaluationChangeToTernaryFixGetsArgsApplied() + { + var source = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + if (something) + { + a = Method(1); + } + else + { + a = Method(2 + 2); + } + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a) => a; + + public void Foo() + { + var something = true; + int a; + a = Method(something?1:2 + 2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task WhenUsingIfAndElseWithAssignmentToAnInterfaceVariableAFittingCastIsInserted() + { + var source = @" + System.Collections.Generic.IEnumerable e= null; + if (true) + e = new int[10]; + else + e = new System.Collections.Generic.List(); + ".WrapInCSharpMethod(); + var fixtest = @" + System.Collections.Generic.IEnumerable e= null; + e = true ? (System.Collections.Generic.IEnumerable)new int[10] : new System.Collections.Generic.List(); + ".WrapInCSharpMethod(); + await VerifyCSharpFixAsync(source, fixtest); + } } public class TernaryOperatorWithReturnTests : CodeFixVerifier @@ -723,5 +802,585 @@ public static Base Foo() "; await VerifyCSharpFixAsync(source, fixtest); } + + [Fact] + public async Task WhenReturnStatementContainsMethodCallAnalyzerCreatesDiagnostic() + { + var source = @" + private int Method(int i) => i; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var expected = new DiagnosticResult + { + Id = DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), + Message = "You can use a ternary operator.", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 17) } + }; + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithSingleDifferentArgumentGetsArgsApplied() + { + var source = @" + private int Method(int i) => i; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i) => i; + + public int Foo() + { + return Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereSingleDifferentGetsArgsApplied() + { + var source = @" + private int Method(int i, string t) => i; + + public int Foo() + { + if (true) + return Method(1, ""hello""); + else + return Method(2, ""hello""); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i, string t) => i; + + public int Foo() + { + return Method(true?1:2, ""hello""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodWithMultipleArgumentsWhereMultipleDifferentGetsArgsNotApplied() + { + var source = @" + private int Method(int i, string t) => i; + + public int Foo() + { + if (true) + return Method(1, ""hello1""); + else + return Method(2, ""hello2""); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int i, string t) => i; + + public int Foo() + { + return true?Method(1,""hello1""):Method(2, ""hello2""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodArgumentsGetCastedWhenGetsArgsApplied() + { + var source = @" + class Base { } + class A : Base { } + class B : Base { } + + private int Method(Base b, string t) => 1; + + public int Foo() + { + if (true) + return Method(new A(), ""hello""); + else + return Method(new B(), ""hello""); + }".WrapInCSharpClass(); + var fixtest = @" + class Base { } + class A : Base { } + class B : Base { } + + private int Method(Base b, string t) => 1; + + public int Foo() + { + return Method(true?(Base)new A():new B(),""hello""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithPrefixedMethodGetsArgsApplied() + { + var source = @" + private int Method(int a) => a; + + public int Foo() + { + if (true) + return this.Method(1); + else + return this.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + private int Method(int a) => a; + + public int Foo() + { + return this.Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfPropertyGetsArgsApplied() + { + var source = @" + class A { + private int Method(int a) => a; + } + + public int Foo() + { + var a=new A(); + if (true) + return a.Method(1); + else + return a.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + class A { + private int Method(int a) => a; + } + + public int Foo() + { + var a=new A(); + return a.Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentPropertyGetsArgsNotApplied() + { + var source = @" + class A { + public int Method(int a) => a; + } + A Prop1 { get { return new A(); } } + A Prop2 { get { return new A(); } } + + public int Foo() + { + if (true) + return this.Prop1.Method(1); + else + return this.Prop2.Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + class A { + public int Method(int a) => a; + } + A Prop1 { get { return new A(); } } + A Prop2 { get { return new A(); } } + + public int Foo() + { + return true?this.Prop1.Method(1):this.Prop2.Method(2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfSameOverloadGetsArgsApplied() + { + var source = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(2); + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + return Method(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentOverloadGetsArgsNotApplied() + { + var source = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + if (true) + return Method(1); + else + return Method(""2""); + }".WrapInCSharpClass(); + var fixtest = @" + int Method(int a)=>a; + int Method(string a)=>1; + + public int Foo() + { + return true?Method(1):Method(""2""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDifferentOverloadButCastingPossibleGetsArgsNotApplied() + { + var source = @" + public class A { } + public class B:A { } + void Method(A a) { }; + void Method(B b) { }; + + public int Foo() + { + if (true) + return Method(new A()); + else + return Method(new B()); + }".WrapInCSharpClass(); + var fixtest = @" + public class A { } + public class B:A { } + void Method(A a) { }; + void Method(B b) { }; + + public int Foo() + { + return true?Method(new A()):Method(new B()); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodNestedInMemberAccessGetsArgsNotApplied() + { + var source = @" + class A { + public int Prop { get; } + } + + A GetA(int i) => new A(); + + public int Foo() + { + if (true) + return GetA(1).Prop; + else + return GetA(2).Prop; + }".WrapInCSharpClass(); + var fixtest = @" + class A { + public int Prop { get; } + } + + A GetA(int i) => new A(); + + public int Foo() + { + return true?GetA(1).Prop:GetA(2).Prop; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodParamOverloadAndNumerOfArgsAreEqualGetsApplied() + { + var source = @" + private int M(params int[] args) { } + + public int Foo() + { + if (true) + return M(1,1); + else + return M(1,2); + }".WrapInCSharpClass(); + var fixtest = @" + private int M(params int[] args) { } + + public int Foo() + { + return M(1,true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodParamOverloadAndNumerOfArgsAreDifferentGetsNotApplied() + { + var source = @" + private int M(params int[] args) { } + + public int Foo() + { + if (true) + return M(1,1); + else + return M(1,2,3); + }".WrapInCSharpClass(); + var fixtest = @" + private int M(params int[] args) { } + + public int Foo() + { + return true?M(1,1):M(1,2,3); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDynamicObjGetsArgsNotApplied() + { + // Calls on dynamic objects get dispatched during runtime. + // Therefore the semantic would be changed if we apply to arguments + // and casting is involved: + // d.M(new A()) else d.M(new B()) -> d.M(cond?(Base)new A():new B()); + // is not the same as cond?d.M(new A()): d.M(new B()) on dynamic objects. + var source = @" + public class Base {} + public class A: Base {} + public class B: Base {} + + public int Foo() + { + dynamic d = new object(); + if (true) + return d.M(new A()); + else + return d.M(new B()); + }".WrapInCSharpClass(); + var fixtest = @" + public class Base {} + public class A: Base {} + public class B: Base {} + + public int Foo() + { + dynamic d = new object(); + return true?d.M(new A()):d.M(new B()); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithMethodOfDynamicObjGetsArgsNeverApplied() + { + // arguments on dynamic method calls are never applied even if it would be save. + // see comments above for why dynamic is dangerous. + var source = @" + public int Foo() + { + dynamic d = new object(); + if (true) + return d.M(1,1); + else + return d.M(1,2); + }".WrapInCSharpClass(); + var fixtest = @" + public int Foo() + { + dynamic d = new object(); + return true?d.M(1,1):d.M(1,2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorGetsArgsApplied() + { + var source = @" + public System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1); + else + return new System.Collections.Generic.List(2); + }".WrapInCSharpClass(); + var fixtest = @" + public System.Collections.Generic.List Foo() + { + return new System.Collections.Generic.List(true?1:2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithIdenticalInitializerGetsArgsApplied() + { + var source = @" + public new System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1) { 1 }; + else + return new System.Collections.Generic.List(2) { 1 }; + }".WrapInCSharpClass(); + var fixtest = @" + public new System.Collections.Generic.List Foo() + { + return new System.Collections.Generic.List(true?1:2) { 1 }; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithDifferentInitializerGetsArgsNotApplied() + { + var source = @" + public System.Collections.Generic.List Foo() + { + if (true) + return new System.Collections.Generic.List(1) { 1 }; + else + return new System.Collections.Generic.List(2) { 1, 2 }; + }".WrapInCSharpClass(); + var fixtest = @" + public System.Collections.Generic.List Foo() + { + return true?new System.Collections.Generic.List(1) { 1 } : new System.Collections.Generic.List(2) { 1, 2 }; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorWithDifferentOverloadsGetArgsNotApplied() + { + var source = @" + public class A + { + public A(int i) { } + public A(string s) { } + } + public A Foo() + { + if (true) + return new A(1); + else + return new A(""1""); + }".WrapInCSharpClass(); + var fixtest = @" + public class A + { + public A(int i) { } + public A(string s) { } + } + public A Foo() + { + return true?new A(1):new A(""1""); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithConstructorOfDifferentObjectsGetArgsNotApplied() + { + var source = @" + public class A + { + public A(int i) { } + } + public class B + { + public B(int i) { } + } + + public Object Foo() + { + if (true) + return new A(1); + else + return new B(2); + }".WrapInCSharpClass(); + var fixtest = @" + public class A + { + public A(int i) { } + } + public class B + { + public B(int i) { } + } + + public Object Foo() + { + return true?(object)new A(1):new B(2); + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task WhenReturnTypeIsAnInterfaceAFittingCastIsInserted() + { + var source = @" + IComparable GetComparable() + { + if (true) + return 1; + else + return ""1""; + }".WrapInCSharpClass(); + var fixtest = @" + IComparable GetComparable() + { + return true?(IComparable)1 : ""1""; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task FixWhenReturningWithReturnTypeIsExplicitConvertable() + { + var source = @" + double GetNumber() + { + if (true) + return 1; + else + return 1.1; + }".WrapInCSharpClass(); + var fixtest = @" + double GetNumber() + { + return true?(double)1:1.1; + }".WrapInCSharpClass(); + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From fe1b3ea9b9548a85d9e4aa2d85006795346f406c Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 21:40:04 -0300 Subject: [PATCH 163/234] Update TernaryOperatorCodeFixProvider.cs to match master branch --- .../Style/TernaryOperatorCodeFixProvider.cs | 98 +++++++++++++++++-- 1 file changed, 91 insertions(+), 7 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs index 3c8c8a9f1..b36fa9584 100644 --- a/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TernaryOperatorCodeFixProvider.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System; namespace CodeCracker.CSharp.Style { @@ -37,11 +38,10 @@ private static async Task MakeTernaryAsync(Document document, Diagnost var elseStatement = ifStatement.Else; var returnStatementInsideElse = (ReturnStatementSyntax)(elseStatement.Statement is BlockSyntax ? ((BlockSyntax)elseStatement.Statement).Statements.Single() : elseStatement.Statement); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - ExpressionSyntax trueExpression, falseExpression; - TernaryOperatorCodeFixHelper.CreateExpressions(returnStatementInsideIf.Expression, returnStatementInsideElse.Expression, semanticModel, out trueExpression, out falseExpression); + var conditionalExpression = TernaryOperatorCodeFixHelper.CreateExpressions(returnStatementInsideIf.Expression, returnStatementInsideElse.Expression, ifStatement.Condition, semanticModel); var ternary = SyntaxFactory.ReturnStatement( - SyntaxFactory.ConditionalExpression(ifStatement.Condition, trueExpression, falseExpression)) + conditionalExpression) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); @@ -76,14 +76,13 @@ private static async Task MakeTernaryAsync(Document document, Diagnost var assignmentExpressionInsideIf = (AssignmentExpressionSyntax)expressionInsideIf.Expression; var assignmentExpressionInsideElse = (AssignmentExpressionSyntax)expressionInsideElse.Expression; var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - ExpressionSyntax trueExpression, falseExpression; - TernaryOperatorCodeFixHelper.CreateExpressions(assignmentExpressionInsideIf.Right, assignmentExpressionInsideElse.Right, semanticModel, out trueExpression, out falseExpression); + var conditionalExpression = TernaryOperatorCodeFixHelper.CreateExpressions(assignmentExpressionInsideIf.Right, assignmentExpressionInsideElse.Right, ifStatement.Condition, semanticModel); var ternary = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( assignmentExpressionInsideIf.Kind(), assignmentExpressionInsideIf.Left, - SyntaxFactory.ConditionalExpression(ifStatement.Condition, trueExpression, falseExpression))) + conditionalExpression)) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); @@ -95,13 +94,98 @@ private static async Task MakeTernaryAsync(Document document, Diagnost internal static class TernaryOperatorCodeFixHelper { - public static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel, out ExpressionSyntax trueExpression, out ExpressionSyntax falseExpression) + public static ExpressionSyntax CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, ExpressionSyntax ifStatementCondition, SemanticModel semanticModel) + { + + var methodCallArgApplied = TryApplyArgsOnMethodCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (methodCallArgApplied != null) return methodCallArgApplied; + var constructorArgsApplied = TryApplyArgsOnConstructorCalls(ifStatementCondition, ifExpression, elseExpression, semanticModel); + if (constructorArgsApplied != null) return constructorArgsApplied; + var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); + var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); + var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); + ExpressionSyntax trueExpression; ExpressionSyntax falseExpression; + CreateExpressions(ifExpression, elseExpression, ifTypeInfo.Type, elseTypeInfo.Type, + ifTypeInfo.ConvertedType, elseTypeInfo.ConvertedType, typeSyntax, semanticModel, out trueExpression, out falseExpression); + return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); + } + + private static ExpressionSyntax TryApplyArgsOnConstructorCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + { + if (ifExpression is ObjectCreationExpressionSyntax && elseExpression is ObjectCreationExpressionSyntax) + { + var ifObjCreation = ifExpression as ObjectCreationExpressionSyntax; + var elseObjCreation = elseExpression as ObjectCreationExpressionSyntax; + if ((ifObjCreation.Initializer == null && elseObjCreation.Initializer == null) || + ifObjCreation.Initializer != null && elseObjCreation.Initializer != null && + ifObjCreation.Initializer.GetText().ContentEquals(elseObjCreation.Initializer.GetText())) // Initializer are either absent or text equals + { + var ifMethodinfo = semanticModel.GetSymbolInfo(ifObjCreation); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseObjCreation); + if (object.Equals(ifMethodinfo, elseMethodinfo)) //same constructor and overload + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifObjCreation.ArgumentList, elseObjCreation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.ObjectCreationExpression(ifObjCreation.Type, CreateMethodArgumentList(ifStatementCondition, ifObjCreation.ArgumentList, elseObjCreation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel), ifObjCreation.Initializer); + } + } + } + return null; + } + + private static ExpressionSyntax TryApplyArgsOnMethodCalls(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) + { + if (ifExpression is InvocationExpressionSyntax && elseExpression is InvocationExpressionSyntax) + { + var ifInvocation = ifExpression as InvocationExpressionSyntax; + var elseInvocation = elseExpression as InvocationExpressionSyntax; + var ifMethodinfo = semanticModel.GetSymbolInfo(ifInvocation.Expression); + var elseMethodinfo = semanticModel.GetSymbolInfo(elseInvocation.Expression); + if (object.Equals(ifMethodinfo, elseMethodinfo) && ifMethodinfo.CandidateReason != CandidateReason.LateBound) //same method and overload, but not dynamic + { + if (ifInvocation.Expression.GetText().ContentEquals(elseInvocation.Expression.GetText())) //same 'path' to the invocation + { + var findSingleArgumentIndexThatDiffers = FindSingleArgumentIndexThatDiffers(ifInvocation.ArgumentList, elseInvocation.ArgumentList, semanticModel); + if (findSingleArgumentIndexThatDiffers >= 0) + return SyntaxFactory.InvocationExpression(ifInvocation.Expression, CreateMethodArgumentList(ifStatementCondition, ifInvocation.ArgumentList, elseInvocation.ArgumentList, findSingleArgumentIndexThatDiffers, semanticModel)); + } + } + } + return null; + } + + private static ArgumentListSyntax CreateMethodArgumentList(ExpressionSyntax ifStatementCondition, ArgumentListSyntax argList1, ArgumentListSyntax argList2, int argumentIndexThatDiffers, SemanticModel semanticModel) + { + var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); + var argSelector = zipped.Select((args, i) => + (i == argumentIndexThatDiffers) ? + SyntaxFactory.Argument(GetConditionalExpressionForArgument(ifStatementCondition, args.a1.Expression, args.a2.Expression, semanticModel)) + : args.a1); + return SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argSelector)); + } + + private static ConditionalExpressionSyntax GetConditionalExpressionForArgument(ExpressionSyntax ifStatementCondition, ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, SemanticModel semanticModel) { var ifTypeInfo = semanticModel.GetTypeInfo(ifExpression); var elseTypeInfo = semanticModel.GetTypeInfo(elseExpression); var typeSyntax = SyntaxFactory.IdentifierName(ifTypeInfo.ConvertedType.ToMinimalDisplayString(semanticModel, ifExpression.SpanStart)); + ExpressionSyntax trueExpression; ExpressionSyntax falseExpression; CreateExpressions(ifExpression, elseExpression, ifTypeInfo.Type, elseTypeInfo.Type, ifTypeInfo.ConvertedType, elseTypeInfo.ConvertedType, typeSyntax, semanticModel, out trueExpression, out falseExpression); + return SyntaxFactory.ConditionalExpression(ifStatementCondition, trueExpression, falseExpression); + } + + private static int FindSingleArgumentIndexThatDiffers(ArgumentListSyntax argList1, ArgumentListSyntax argList2, SemanticModel semanticModel) + { + if (argList1.Arguments.Count != argList2.Arguments.Count) return -1; // in case of 'params' + var zipped = argList1.Arguments.Zip(argList2.Arguments, (a1, a2) => new { a1, a2 }).Select((a, i) => new { a.a1, a.a2, i }); + var singleMissmatch = zipped.Where(args => + { + var a1Text = args.a1.GetText(); + var a2Text = args.a2.GetText(); + return !a1Text.ContentEquals(a2Text); + }).Take(2).ToList(); + return (singleMissmatch.Count == 1) ? singleMissmatch[0].i : -1; } private static void CreateExpressions(ExpressionSyntax ifExpression, ExpressionSyntax elseExpression, From a62c6c70f0d5ea7ada3c69b15590363b47766e16 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Fri, 23 Jun 2017 03:34:47 +0200 Subject: [PATCH 164/234] Create reusable strategy for fix all See IFixDocumentInternalsOnly. Also add a fix all provider for ReplaceWithGetterOnlyAutoPropertyCodeFixProvider --- ...thGetterOnlyAutoPropertyCodeFixProvider.cs | 61 +++-- .../CodeCracker.Common.csproj | 2 + .../DocumentCodeFixProviderAll.cs | 98 +++++++++ .../IFixDocumentInternalsOnly.cs | 16 ++ .../ReplaceWithGetterOnlyAutoPropertyTests.cs | 208 +++++++++++++++++- 5 files changed, 358 insertions(+), 27 deletions(-) create mode 100644 src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs create mode 100644 src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs diff --git a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs index d22626bae..d8b59a702 100644 --- a/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/ReplaceWithGetterOnlyAutoPropertyCodeFixProvider.cs @@ -12,15 +12,18 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System; +using CodeCracker.FixAllProviders; namespace CodeCracker.CSharp.Refactoring { [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ReplaceWithGetterOnlyAutoPropertyCodeFixProvider)), Shared] - public class ReplaceWithGetterOnlyAutoPropertyCodeFixProvider : CodeFixProvider + public class ReplaceWithGetterOnlyAutoPropertyCodeFixProvider : CodeFixProvider, IFixDocumentInternalsOnly { + private static readonly FixAllProvider FixAllProvider = new DocumentCodeFixProviderAll(Resources.ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title); public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId()); - public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + public override FixAllProvider GetFixAllProvider() => FixAllProvider; public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { @@ -35,19 +38,32 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) diagnostic); return Task.FromResult(0); } - private async static Task ReplaceByGetterOnlyAutoPropertyAsync(Document document, TextSpan propertyDeclarationSpan, CancellationToken cancellationToken) + private async Task ReplaceByGetterOnlyAutoPropertyAsync(Document document, TextSpan propertyDeclarationSpan, CancellationToken cancellationToken) { - var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - var root = await document.GetSyntaxRootAsync(cancellationToken); - var token = root.FindToken(propertyDeclarationSpan.Start); - var property = token.Parent.AncestorsAndSelf().OfType().First(); - var fieldVariableDeclaratorSyntax = await GetFieldDeclarationSyntaxNodeAsync(property, cancellationToken, semanticModel); - if (fieldVariableDeclaratorSyntax == null) return document; - var fieldReferences = await GetFieldReferencesAsync(fieldVariableDeclaratorSyntax, cancellationToken, semanticModel); + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var node = root.FindNode(propertyDeclarationSpan); + return await FixDocumentAsync(node, document, cancellationToken).ConfigureAwait(false); + } + + public async Task FixDocumentAsync(SyntaxNode nodeWithDiagnostic, Document document, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false); + var newRoot = await ReplacePropertyInSyntaxRootAsync(nodeWithDiagnostic, cancellationToken, semanticModel, root).ConfigureAwait(false); + var newDocument = document.WithSyntaxRoot(newRoot); + return newDocument; + } + + + private static async Task ReplacePropertyInSyntaxRootAsync(SyntaxNode propertyDeclarationSyntaxNode, CancellationToken cancellationToken, SemanticModel semanticModel, SyntaxNode root) + { + var property = propertyDeclarationSyntaxNode.AncestorsAndSelf().OfType().First(); + var fieldVariableDeclaratorSyntax = await GetFieldDeclarationSyntaxNodeAsync(property, cancellationToken, semanticModel).ConfigureAwait(false); + if (fieldVariableDeclaratorSyntax == null) return root; + var fieldReferences = await GetFieldReferencesAsync(fieldVariableDeclaratorSyntax, cancellationToken, semanticModel).ConfigureAwait(false); var nodesToUpdate = fieldReferences.Cast().Union(Enumerable.Repeat(property, 1)).Union(Enumerable.Repeat(fieldVariableDeclaratorSyntax, 1)); var newRoot = FixWithTrackNode(root, property, fieldVariableDeclaratorSyntax, nodesToUpdate); - var resultDocument = document.WithSyntaxRoot(newRoot); - return resultDocument; + return newRoot; } private static SyntaxNode FixWithTrackNode(SyntaxNode root, PropertyDeclarationSyntax property, VariableDeclaratorSyntax fieldVariableDeclaratorSyntax, IEnumerable nodesToUpdate) @@ -102,16 +118,19 @@ private static async Task> GetFieldReferencesA HashSet fieldReferences = null; var fieldSymbol = semanticModel.GetDeclaredSymbol(fieldDeclarationSyntax, cancellationToken); var declaredInType = fieldSymbol.ContainingType; - var reference = declaredInType.DeclaringSyntaxReferences[0]; - var allNodes = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); - var allFieldReferenceNodes = from n in allNodes.OfType() - where n.Identifier.Text == fieldSymbol.Name - let nodeSymbolInfo = semanticModel.GetSymbolInfo(n, cancellationToken) - where object.Equals(nodeSymbolInfo.Symbol, fieldSymbol) - select n; - foreach (var fieldReference in allFieldReferenceNodes) + var references = declaredInType.DeclaringSyntaxReferences.Where(r => r.SyntaxTree == semanticModel.SyntaxTree); + foreach (var reference in references) { - (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); + var allNodes = (await reference.GetSyntaxAsync(cancellationToken)).DescendantNodes(); + var allFieldReferenceNodes = from n in allNodes.OfType() + where n.Identifier.Text == fieldSymbol.Name + let nodeSymbolInfo = semanticModel.GetSymbolInfo(n, cancellationToken) + where object.Equals(nodeSymbolInfo.Symbol, fieldSymbol) + select n; + foreach (var fieldReference in allFieldReferenceNodes) + { + (fieldReferences ?? (fieldReferences = new HashSet())).Add(fieldReference); + } } return fieldReferences ?? Enumerable.Empty(); } diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index f20344f73..34f859b17 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -40,6 +40,8 @@ + + diff --git a/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs b/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs new file mode 100644 index 000000000..7a885fcef --- /dev/null +++ b/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs @@ -0,0 +1,98 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeCracker.FixAllProviders +{ + + public sealed class DocumentCodeFixProviderAll : FixAllProvider + { + private const string SyntaxAnnotationKey = "DocumentCodeFixProviderAllSyntaxAnnotation"; + + public DocumentCodeFixProviderAll(string codeFixTitle) + { + CodeFixTitle = codeFixTitle; + } + + private string CodeFixTitle { get; } + + public override Task GetFixAsync(FixAllContext fixAllContext) + { + switch (fixAllContext.Scope) + { + case FixAllScope.Document: + return Task.FromResult(CodeAction.Create(CodeFixTitle, + ct => GetFixedDocumentsAsync(fixAllContext, Enumerable.Repeat(fixAllContext.Document, 1)))); + case FixAllScope.Project: + return Task.FromResult(CodeAction.Create(CodeFixTitle, + ct => GetFixedDocumentsAsync(fixAllContext, fixAllContext.Project.Documents))); + case FixAllScope.Solution: + return Task.FromResult(CodeAction.Create(CodeFixTitle, + ct => GetFixedDocumentsAsync(fixAllContext, fixAllContext.Solution.Projects.SelectMany(p => p.Documents)))); + } + return null; + } + + private async static Task GetFixedDocumentsAsync(FixAllContext fixAllContext, IEnumerable documents) + { + var solution = fixAllContext.Solution; + var newDocuments = documents.ToDictionary(d => d.Id, d => GetFixedDocumentAsync(fixAllContext, d)); + await Task.WhenAll(newDocuments.Values).ConfigureAwait(false); + var changedDocuments = from kvp in newDocuments + where kvp.Value.Result != null + select new { DocumentId = kvp.Key, Document = kvp.Value.Result }; + foreach (var newDocument in changedDocuments) + solution = solution.WithDocumentSyntaxRoot(newDocument.DocumentId, await newDocument.Document.GetSyntaxRootAsync().ConfigureAwait(false)); + return solution; + } + + private async static Task GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) + { + var codeFixer = fixAllContext.CodeFixProvider as IFixDocumentInternalsOnly; + if (codeFixer == null) throw new ArgumentException("This CodeFixAllProvider requires that your CodeFixProvider implements the IFixDocumentInternalsOnly."); + var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); + if (diagnostics.Length == 0) return null; + var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); + var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing); + var annotations = new List(); + var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => + { + var annotation = new SyntaxAnnotation(SyntaxAnnotationKey); + annotations.Add(annotation); + var newNode = original.WithAdditionalAnnotations(annotation); + return newNode; + }); + var newDocument = document.WithSyntaxRoot(newRoot); + newDocument = await FixCodeForAnnotatedNodesAsync(newDocument, codeFixer, annotations, fixAllContext.CancellationToken).ConfigureAwait(false); + newDocument = await RemoveAnnontationsAsync(newDocument, annotations).ConfigureAwait(false); + return newDocument; + } + + private static async Task FixCodeForAnnotatedNodesAsync(Document document, IFixDocumentInternalsOnly codeFixer, IEnumerable annotations, CancellationToken cancellationToken) + { + foreach (var annotation in annotations) + { + var newRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var annotatedNodes = newRoot.GetAnnotatedNodes(annotation); + var node = annotatedNodes.FirstOrDefault(); + if (node == null) continue; + document = await codeFixer.FixDocumentAsync(node, document, cancellationToken).ConfigureAwait(false); + } + return document; + } + + private static async Task RemoveAnnontationsAsync(Document document, IEnumerable annotations) + { + var root = await document.GetSyntaxRootAsync().ConfigureAwait(false); + var nodes = annotations.SelectMany(annotation => root.GetAnnotatedNodes(annotation)); + root = root.ReplaceNodes(nodes, (original, rewritten) => original.WithoutAnnotations(annotations)); + var newDocument = document.WithSyntaxRoot(root); + return newDocument; + } + } +} \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs b/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs new file mode 100644 index 000000000..735c76cfa --- /dev/null +++ b/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs @@ -0,0 +1,16 @@ +using Microsoft.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeCracker.FixAllProviders +{ + /// + /// This interface must be implemented by the associated CodeFixProvider. The CodeFixProvider must operate on a single document and + /// should only change the document. This limits the possible operations of the CodeFixProvider to change only document internals without + /// effecting other parts of the solution. + /// + public interface IFixDocumentInternalsOnly + { + Task FixDocumentAsync(SyntaxNode nodeWithDiagnostic, Document document, CancellationToken cancellationToken); + } +} diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs index d7ffc711d..072643c56 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs @@ -430,7 +430,7 @@ class InnerClass { [Fact] public async Task FieldWithSameNameInOtherClassIsNotRenamed() { - var test = @" + const string test = @" using System; namespace App { public class C1 @@ -455,7 +455,7 @@ public class C2 readonly int _A; } }"; - var fixtest = @" + const string fixtest = @" using System; namespace App { public class C1 @@ -510,7 +510,7 @@ public TypeName(int A) } [Fact] - public async Task FieldReferencesInPartialClassesGetNotRenamedAndCasueCompilerErrorCS0103() + public async Task FieldReferencesInPartialClassesGetRenamedIfInTheSameDocument() { const string test = @" namespace A @@ -544,11 +544,10 @@ public A1(int i) } public partial class A1 { - public void Print() => Console.Write(_I); + public void Print() => Console.Write(I); } }"; - //Console.Write(_I); causes CS0103 The name '_I' does not exist in the current context - await VerifyCSharpFixAsync(oldSource: test, newSource: fixtest, allowNewCompilerDiagnostics: true); + await VerifyCSharpFixAsync(oldSource: test, newSource: fixtest, allowNewCompilerDiagnostics: false); } [Fact] @@ -600,5 +599,202 @@ public partial class A1 //Console.Write(_I); causes CS0103 The name '_I' does not exist in the current context await VerifyCSharpFixAllAsync(oldSources: new string[] { testPart1, testPart2 }, newSources: new string[] { fixtestPart1, fixtestPart2 }, allowNewCompilerDiagnostics: true); } + + #region FixAll Tests + + [Fact] + public async Task ReplaceMultiplePropertiesInOneClassFixAllTest() + { + var source1 = @" + readonly int _A; + readonly int _B; + readonly string _C; + + public TypeName(int a, int b, string c) + { + _A=a; + _B=b; + _C=c; + } + public int A { get { return _A; } } + public int B { get { return _B; } } + public string C { get { return _C; } } + ".WrapInCSharpClass(); + var fixtest1 = @" + public TypeName(int a, int b, string c) + { + A=a; + B=b; + C=c; + } + public int A { get; } + public int B { get; } + public string C { get; } + ".WrapInCSharpClass(); + await VerifyCSharpFixAllAsync(new[] { source1 }, new[] { fixtest1 }); + } + + [Fact] + public async Task ReplaceMultiplePropertiesInOneClassInMultipleDocumentsFixAllTest() + { + const string source1 = @" + namespace A + { + public class A1 + { + readonly int _A; + readonly int _B; + readonly string _C; + public A1(int a, int b, string c) + { + _A=a; + _B=b; + _C=c; + } + public int A { get { return _A; } } + public int B { get { return _B; } } + public string C { get { return _C; } } + } + }"; + const string source2 = @" + namespace A + { + public class A2 + { + readonly int _A; + readonly int _B; + readonly string _C; + public A2(int a, int b, string c) + { + _A=a; + _B=b; + _C=c; + } + public int A { get { return _A; } } + public int B { get { return _B; } } + public string C { get { return _C; } } + } + }"; + const string source3 = @" + namespace B + { + public class B1 + { + readonly int _A; + readonly int _B; + readonly string _C; + public B1(int a, int b, string c) + { + _A=a; + _B=b; + _C=c; + } + public int A { get { return _A; } } + public int B { get { return _B; } } + public string C { get { return _C; } } + } + }"; + const string fixtest1 = @" + namespace A + { + public class A1 + { + public A1(int a, int b, string c) + { + A=a; + B=b; + C=c; + } + public int A { get; } + public int B { get; } + public string C { get; } + } + }"; + const string fixtest2 = @" + namespace A + { + public class A2 + { + public A2(int a, int b, string c) + { + A=a; + B=b; + C=c; + } + public int A { get; } + public int B { get; } + public string C { get; } + } + }"; + const string fixtest3 = @" + namespace B + { + public class B1 + { + public B1(int a, int b, string c) + { + A=a; + B=b; + C=c; + } + public int A { get; } + public int B { get; } + public string C { get; } + } + }"; + await VerifyCSharpFixAllAsync(new[] { source1, source2, source3 }, new[] { fixtest1, fixtest2, fixtest3 }); + } + + [Fact] + public async Task ReplaceMultiplePropertiesInOneClassInMultipleDocumentsAndKeepExisitingDocumentsWithoutDiagnosticsFixAllTest() + { + const string source1 = @" + namespace A + { + public class A1 + { + readonly int _A; + readonly int _B; + readonly string _C; + public A1(int a, int b, string c) + { + _A=a; + _B=b; + _C=c; + } + public int A { get { return _A; } } + public int B { get { return _B; } } + public string C { get { return _C; } } + } + }"; + const string source2 = @" + namespace A + { + public class A2 + { + public A2() + { + } + } + }"; + const string fixtest1 = @" + namespace A + { + public class A1 + { + public A1(int a, int b, string c) + { + A=a; + B=b; + C=c; + } + public int A { get; } + public int B { get; } + public string C { get; } + } + }"; + await VerifyCSharpFixAllAsync(new[] { source1, source2 }, new[] { fixtest1, source2 }); + } + #endregion } } \ No newline at end of file From d6d7bdf720d5ddad627d744dcd8dea945b83420b Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Thu, 22 Jun 2017 22:36:58 -0300 Subject: [PATCH 165/234] Fix typo --- .../FixAllProviders/DocumentCodeFixProviderAll.cs | 4 ++-- .../FixAllProviders/IFixDocumentInternalsOnly.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs b/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs index 7a885fcef..255dfc074 100644 --- a/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs +++ b/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs @@ -69,7 +69,7 @@ private async static Task GetFixedDocumentAsync(FixAllContext fixAllCo }); var newDocument = document.WithSyntaxRoot(newRoot); newDocument = await FixCodeForAnnotatedNodesAsync(newDocument, codeFixer, annotations, fixAllContext.CancellationToken).ConfigureAwait(false); - newDocument = await RemoveAnnontationsAsync(newDocument, annotations).ConfigureAwait(false); + newDocument = await RemoveAnnotationsAsync(newDocument, annotations).ConfigureAwait(false); return newDocument; } @@ -86,7 +86,7 @@ private static async Task FixCodeForAnnotatedNodesAsync(Document docum return document; } - private static async Task RemoveAnnontationsAsync(Document document, IEnumerable annotations) + private static async Task RemoveAnnotationsAsync(Document document, IEnumerable annotations) { var root = await document.GetSyntaxRootAsync().ConfigureAwait(false); var nodes = annotations.SelectMany(annotation => root.GetAnnotatedNodes(annotation)); diff --git a/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs b/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs index 735c76cfa..901942669 100644 --- a/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs +++ b/src/Common/CodeCracker.Common/FixAllProviders/IFixDocumentInternalsOnly.cs @@ -13,4 +13,4 @@ public interface IFixDocumentInternalsOnly { Task FixDocumentAsync(SyntaxNode nodeWithDiagnostic, Document document, CancellationToken cancellationToken); } -} +} \ No newline at end of file From 8f48dfea083cf3583b6af449981b9b76a76e0ab4 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 24 Jun 2017 00:12:33 -0300 Subject: [PATCH 166/234] Use latest msbuild --- build.ps1 | 2 +- default.ps1 | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/build.ps1 b/build.ps1 index 821027472..27cd8f2d8 100644 --- a/build.ps1 +++ b/build.ps1 @@ -73,7 +73,7 @@ Get-Nuget Import-Psake Import-ILMerge if ($MyInvocation.UnboundArguments.Count -ne 0) { - Invoke-Expression("Invoke-psake -framework '4.5.2' $PSScriptRoot\default.ps1 -taskList " + $MyInvocation.UnboundArguments -join " ") + Invoke-Expression("Invoke-psake -framework '4.6' $PSScriptRoot\default.ps1 -taskList " + $MyInvocation.UnboundArguments -join " ") } else { . $PSScriptRoot\build.ps1 Build diff --git a/default.ps1 b/default.ps1 index a36f5fad6..aef7b7d5d 100644 --- a/default.ps1 +++ b/default.ps1 @@ -38,6 +38,10 @@ Properties { $isRelease = $isAppVeyor -and (($env:APPVEYOR_REPO_BRANCH -eq "release") -or ($env:APPVEYOR_REPO_TAG -eq "true")) $isPullRequest = $env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null $tempDir = Join-Path "$([System.IO.Path]::GetTempPath())" "CodeCracker" + # msbuild hack necessary until https://github.com/psake/psake/issues/201 is fixed: + $msbuild64 = Resolve-Path "$(if (${env:ProgramFiles(x86)}) { ${env:ProgramFiles(x86)} } else { $env:ProgramFiles } )\Microsoft Visual Studio\2017\*\MSBuild\15.0\Bin\msbuild.exe" + $msbuild32 = Resolve-Path "$(if (${env:ProgramFiles(x86)}) { ${env:ProgramFiles(x86)} } else { $env:ProgramFiles } )\Microsoft Visual Studio\2017\*\MSBuild\15.0\Bin\msbuild.exe" + $msbuild = if ($msbuild64) { $msbuild64 } else { $msbuild32 } } FormatTaskName (("-"*25) + "[{0}]" + ("-"*25)) @@ -62,17 +66,17 @@ Task Build-Only -depends Build-Only-CS, Build-Only-VB Task Build-Only-CS -depends Build-MSBuild-CS, ILMerge-CS Task Build-MSBuild-CS { if ($isAppVeyor) { - Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } + Exec { . $msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } } else { - Exec { msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } + Exec { . $msbuild $solutionFileCS /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } } } Task Build-Only-VB -depends Build-MSBuild-VB, ILMerge-VB Task Build-MSBuild-VB { if ($isAppVeyor) { - Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } + Exec { . $msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" } } else { - Exec { msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } + Exec { . $msbuild $solutionFileVB /m /verbosity:minimal /p:Configuration=ReleaseNoVsix } } } @@ -120,8 +124,8 @@ function Change-Extension ($filename, $extension) { } Task Clean { - Exec { msbuild $solutionFileCS /t:Clean /v:quiet } - Exec { msbuild $solutionFileVB /t:Clean /v:quiet } + Exec { . $msbuild $solutionFileCS /t:Clean /v:quiet } + Exec { . $msbuild $solutionFileVB /t:Clean /v:quiet } } Task Set-Log { From 6de6d0745daf942454555887939e900cd54cf228 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Sat, 24 Jun 2017 05:35:29 +0200 Subject: [PATCH 167/234] Fix bug for CC0118 Remove to string The string is only removed if safe to do. Fixes #866. Implemented option 2 as requested in #866. This fix now looks up the types of both sides of the plus operator and tries removes those candidates, that might break things. It turned out, that some of the checks in CheckAddOperationOverloadsOfTypes are not needed (After the second check every other check returns false). Essentially right now the removal of "ToString" is only save if either the underlying type is a string (as in 1 + "a".ToString()) or the type on the other side of the plus operator is a string (as in "a" + 1.ToString()). I kept all the other checks for future enhancements to make clear that there are several cases to consider. Further I added lots of unit tests to cover these cases. The idea is that CheckAddOperationOverloadsOfTypes can easily be expanded in the future to support more cases without breaking anything. Those redundant checks are also very cheap and are essentially just simple comparisons. --- ...ryToStringInStringConcatenationAnalyzer.cs | 132 +++++++++++++- ...ssaryToStringInStringConcatenationTests.cs | 170 ++++++++++++++++-- 2 files changed, 288 insertions(+), 14 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs index d2c56f355..23fa9dcbe 100644 --- a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs @@ -3,9 +3,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Threading; namespace CodeCracker.CSharp.Style { @@ -45,7 +47,9 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (!hasInvocationExpression) return; var invocationExpressionsThatHaveToStringCall = GetInvocationExpressionsThatHaveToStringCall(addExpression); - foreach (var expression in invocationExpressionsThatHaveToStringCall) + var redundantToStringCalls = FilterInvocationsThatAreRedundant(invocationExpressionsThatHaveToStringCall, addExpression, context.SemanticModel, context.CancellationToken); + + foreach (var expression in redundantToStringCalls) { var lastDot = expression.Expression.ChildNodesAndTokens().Last(x => x.IsKind(SyntaxKind.DotToken)); var toStringTextSpan = new TextSpan(lastDot.Span.Start, expression.ArgumentList.Span.End - lastDot.Span.Start); @@ -60,5 +64,131 @@ private static IEnumerable GetInvocationExpressionsT //Only default call to ToString method must be accepted .Where(x => x.Expression.ToString().EndsWith(@".ToString") && !x.ArgumentList.Arguments.Any()); } + + private static IEnumerable FilterInvocationsThatAreRedundant(IEnumerable invocationExpressionsThatHaveToStringCall, BinaryExpressionSyntax addExpression, SemanticModel semanticModel, CancellationToken cancellationToken) + { + foreach (var node in invocationExpressionsThatHaveToStringCall) + { + var toStringReceiver = GetTypeInfoOfReceiverOfToStringCall(node, semanticModel, cancellationToken); + //As long as the underlying type can not be resolved by the compiler (e.g. undefined type) + //removal is not save. + if (toStringReceiver == null || toStringReceiver.TypeKind==TypeKind.Error) + continue; + //If the underlying type is string, removal is save. + if (IsTypeSymbolSystem_String(toStringReceiver)) + yield return node; + var otherType = GetTypeInfoOfOtherNode(node, addExpression, semanticModel, cancellationToken); + if (otherType != null) + { + if (CheckAddOperationOverloadsOfTypes(toStringReceiver, otherType)) + { + yield return node; + } + } + } + } + + private static ITypeSymbol GetTypeInfoOfReceiverOfToStringCall(InvocationExpressionSyntax toStringCall, SemanticModel semanticModel, CancellationToken cancellationToken) + { + if (toStringCall.Expression is MemberAccessExpressionSyntax memberAccess) + { + return semanticModel.GetTypeInfo(memberAccess.Expression, cancellationToken).Type; + } + + return null; + } + + private static ITypeSymbol GetTypeInfoOfOtherNode(SyntaxNode toStringNode, BinaryExpressionSyntax addExpression, SemanticModel semanticModel, CancellationToken cancellationToken) + { + var otherNode = addExpression.Left == toStringNode + ? addExpression.Right + : addExpression.Right == toStringNode + ? addExpression.Left + : null; + if (otherNode != null) + { + return semanticModel.GetTypeInfo(otherNode, cancellationToken).Type; + } + + return null; + } + + private static bool CheckAddOperationOverloadsOfTypes(ITypeSymbol toStringReceiver, ITypeSymbol otherType) + { + //If the underlying type has a custom AddOperator this operator will take precedence over everything else + if (HasTypeCustomAddOperator(toStringReceiver)) + { + return false; + } + + //If the other side is a string the string concatenation will be applied and "ToString" will be implicit called by the concatenation operator + if (IsTypeSymbolSystem_String(otherType)) + { + return true; + } + + //If the underlying type is one of the build in types (numeric, datetime and so on) and the other side is not a string, + //the result a removal is hard to predict and might be wrong. + if (HasAdditionOperator(toStringReceiver)) + { + return false; + } + + //If both sides are delegates, the plus operator combines the delegates: + //https://msdn.microsoft.com/en-us/library/ms173175(v=vs.110).aspx + if (IsTypeSmybolDelegateType(toStringReceiver) && IsTypeSmybolDelegateType(otherType)) + { + return false; + } + + //There might be more cases were removal is save but for now we opt out. + return false; + } + + private static bool IsTypeSmybolDelegateType(ITypeSymbol typeSymbol) + => typeSymbol.TypeKind == TypeKind.Delegate; + + private static bool IsTypeSymbolSystem_String(ITypeSymbol typeSymbol) + => typeSymbol.SpecialType == SpecialType.System_String; + + + // see https://stackoverflow.com/a/41223159 + private static bool HasAdditionOperator(ITypeSymbol type) + { + switch (type.SpecialType) + { + case SpecialType.System_Enum: + case SpecialType.System_Boolean: + case SpecialType.System_Char: + case SpecialType.System_SByte: + case SpecialType.System_Byte: + case SpecialType.System_Int16: + case SpecialType.System_UInt16: + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Decimal: + case SpecialType.System_Single: + case SpecialType.System_Double: + //String has an addition operator but we are looking for types other than string with an addition overload. + //case SpecialType.System_String: + case SpecialType.System_IntPtr: + case SpecialType.System_UIntPtr: + case SpecialType.System_DateTime: + return true; + } + if (type.TypeKind == TypeKind.Enum) + { + return true; + } + return false; + } + + private static bool HasTypeCustomAddOperator(ITypeSymbol type) + { + var customAdditionOperators = type.GetMembers("op_Addition").OfType(); + return customAdditionOperators.Any(ms => ms.MethodKind == MethodKind.UserDefinedOperator); + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs b/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs index 077f095e7..d6073bcad 100644 --- a/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs @@ -7,6 +7,19 @@ namespace CodeCracker.Test.CSharp.Style { public class UnnecessaryToStringInStringConcatenationTests : CodeFixVerifier { + private static DiagnosticResult CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(int expectedRow, int expectedColumn) + { + var expected = new DiagnosticResult + { + Id = DiagnosticId.UnnecessaryToStringInStringConcatenation.ToDiagnosticId(), + Message = "Unnecessary '.ToString()' call in string concatenation.", + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", expectedRow, expectedColumn) } + }; + + return expected; + } + [Fact] public async Task InstantiatingAnObjectAndCallToStringInsideAStringConcatenationShouldGenerateDiagnosticResult() { @@ -20,9 +33,9 @@ public async Task InstantiatingAnObjectAndCallToStringInsideAStringConcatenation [Fact] public async Task InstantiatingAnStringBuilderAndCallToStringInsideAStringConcatenationShouldGenerateDiagnosticResult() { - const string source = @"var foo = ""a"" + new System.Text.StringBuilder().ToString();"; + var source = @"var foo = ""a"" + new System.Text.StringBuilder().ToString();".WrapInCSharpMethod(); - var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(1, 48); + var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(10, 64); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -37,9 +50,9 @@ namespace ConsoleApplication1 { class AuxClass { - public override void ToString() + public override string ToString() { - return ""Test""; + return ""Test""; } } @@ -51,7 +64,7 @@ public void Foo() var bar = ""a"" + new AuxClass().ToString(); var foo = ""a"" + auxClass.ToString(); - var far = ""a"" + new AuxClass().ToString() + auxClass.ToString() + new object().ToString(""C""); + var far = ""a"" + new AuxClass().ToString() + auxClass.ToString() + new int().ToString(""C""); } } }"; @@ -66,6 +79,35 @@ public void Foo() await VerifyCSharpDiagnosticAsync(test, expected); } + [Fact] + public async Task CallToStringOnStringExpressionsShouldGenerateDiagnosticResult() + { + const string test = @"var t1 = (true ? ""1"" : ""2"") + new object().ToString();"; + + var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(1, 43); + + await VerifyCSharpDiagnosticAsync(test, expected); + } + + [Fact] + public async Task CallToStringFollowedByACallToAStringMethodShouldNotGenerateDiagnosticResult() + { + const string source = @"var salary = ""salary: "" + 1000.ToString().Trim();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task CallToLambdaNamedToStringShouldNotGenerateDiagnosticResult() + { + var source = @" + Func ToString = () => ""Dummy""; + var t = 1 + ToString(); + ".WrapInCSharpMethod(); + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + [Fact] public async Task CallToStringInsideAStringConcatenationWithAFormatParameterShouldNotGenerateDiagnosticResult() { @@ -83,18 +125,120 @@ public async Task CallToStringOutsideAStringConcatenationWithoutParameterShouldN await VerifyCSharpHasNoDiagnosticsAsync(source); } + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_NumericAddition_RightSide() + { + const string source = @"var value = 1 + 2.ToString();"; - private static DiagnosticResult CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(int expectedRow, int expectedColumn) + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_NumericAddition_LeftSide() { - var expected = new DiagnosticResult + const string source = @"var value = 2.ToString() + 1;"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_NumericAddition_WithExpression() + { + const string source = @"var value = (1 + 1) + 2.ToString();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_NumericAddition_Double() + { + const string source = @"var value = (true ? 1.1 : 0.99) + 2.ToString();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_NumericAddition_DateTime() + { + const string source = @"var value = new System.DateTime(2000, 1, 1) + 2.ToString();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_CompilerGeneratedEnumOperator() + { + const string source = @"var value = System.AttributeTargets.Assembly + System.AttributeTargets.Module.ToString();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_UnderlyingTypeDoesntHaveAddOperatorOverload() + { + const string source = @"var value = new System.Random() + new System.Random().ToString();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_UserDefinedOperator() + { + const string source = @" + namespace A + { + public class C1 + { + public static string operator +(C1 c, object o) => ""Dummy""; + } + + public class C2 + { + public void M() { - Id = DiagnosticId.UnnecessaryToStringInStringConcatenation.ToDiagnosticId(), - Message = "Unnecessary '.ToString()' call in string concatenation.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", expectedRow, expectedColumn) } - }; + var t = new C1().ToString() + ""a""; + } + } + } +"; - return expected; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfOtherOverloadsTakePrecedence_DelegateCombination() + { + var source = @" + var ea1 = new System.EventHandler((o, e) => { }); + var ea2 = new System.EventHandler((o, e) => { }); + var t = ea1 + ea2.ToString(); + ".WrapInCSharpMethod(); + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfTheTypesOfTheOperationAreNotResovable_ToStringReceiver() + { + const string source = @"var t = new UndefinedType().ToString() + ""a"""; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfTheTypesOfTheOperationAreNotResovable_OtherSide() + { + const string source = @"var t = 1.ToString() + new UndefinedType();"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task AStringConcatinationShouldNotBeRemovedIfTheTypesOfTheOperationAreNotResovable_SyntaxError() + { + const string source = @"var t = new System.Random().ToString() + new ThisIsAnSyntaxError"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); } [Fact] From 155634dae288bb7dafa2af7a7e82047d97d28983 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 28 Jun 2017 01:48:29 +0200 Subject: [PATCH 168/234] Use default fixall for IntroduceFieldFromConstructor/CC0071 From #940. --- src/CSharp/CodeCracker/CodeCracker.csproj | 1 - .../IntroduceFieldFromConstructorAnalyzer.cs | 9 ++- ...duceFieldFromConstructorCodeFixProvider.cs | 25 +++++-- ...eFieldFromConstructorCodeFixProviderAll.cs | 73 ------------------- .../Properties/Resources.Designer.cs | 45 ++++++++++++ .../Properties/Resources.resx | 15 ++++ 6 files changed, 83 insertions(+), 85 deletions(-) delete mode 100644 src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProviderAll.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index ea63f7981..715a8f4ac 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -74,7 +74,6 @@ - diff --git a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs index 91562e3db..7b20fe932 100644 --- a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorAnalyzer.cs @@ -1,4 +1,5 @@ -using Microsoft.CodeAnalysis; +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -11,10 +12,10 @@ namespace CodeCracker.CSharp.Refactoring [DiagnosticAnalyzer(LanguageNames.CSharp)] public class IntroduceFieldFromConstructorAnalyzer : DiagnosticAnalyzer { - internal const string Title = "Consider introduce field for constructor parameters."; - internal const string MessageFormat = "Introduce a field for parameter: {0}"; internal const string Category = SupportedCategories.Refactoring; - const string Description = "Consider introduce field for constructor parameters."; + internal static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.IntroduceFieldFromConstructorAnalyzer_Title), Resources.ResourceManager, typeof(Resources)); + internal static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.IntroduceFieldFromConstructorAnalyzer_Description), Resources.ResourceManager, typeof(Resources)); + internal static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.IntroduceFieldFromConstructorAnalyzer_MessageFormat), Resources.ResourceManager, typeof(Resources)); internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.IntroduceFieldFromConstructor.ToDiagnosticId(), diff --git a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs index 085196f21..9351d73b9 100644 --- a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProvider.cs @@ -1,3 +1,5 @@ +using CodeCracker.FixAllProviders; +using CodeCracker.Properties; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; @@ -14,12 +16,14 @@ namespace CodeCracker.CSharp.Refactoring { [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(IntroduceFieldFromConstructorCodeFixProvider)), Shared] - public class IntroduceFieldFromConstructorCodeFixProvider : CodeFixProvider + public sealed class IntroduceFieldFromConstructorCodeFixProvider : CodeFixProvider, IFixDocumentInternalsOnly { + private static readonly FixAllProvider FixAllProvider = new DocumentCodeFixProviderAll(Resources.IntroduceFieldFromConstructorCodeFixProvider_Title); + private static readonly string MessageFormat = Resources.IntroduceFieldFromConstructorCodeFixProvider_MessageFormat; + public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.IntroduceFieldFromConstructor.ToDiagnosticId()); - public readonly static string MessageFormat = "Introduce field: {0} from constructor."; - public sealed override FixAllProvider GetFixAllProvider() => IntroduceFieldFromConstructorCodeFixAllProvider.Instance; + public sealed override FixAllProvider GetFixAllProvider() => FixAllProvider; public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { @@ -29,17 +33,24 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) return Task.FromResult(0); } - public async static Task IntroduceFieldFromConstructorDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + public async Task FixDocumentAsync(SyntaxNode nodeWithDiagnostic, Document document, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var diagnosticSpan = diagnostic.Location.SourceSpan; - var parameter = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); - var constructor = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); + var parameter = nodeWithDiagnostic.AncestorsAndSelf().OfType().First(); + var constructor = nodeWithDiagnostic.AncestorsAndSelf().OfType().First(); var newRoot = IntroduceFieldFromConstructor(root, constructor, parameter); var newDocument = document.WithSyntaxRoot(newRoot); return document.WithSyntaxRoot(newRoot); } + public async Task IntroduceFieldFromConstructorDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var diagnosticSpan = diagnostic.Location.SourceSpan; + var nodeWithDiagnostic = root.FindToken(diagnosticSpan.Start).Parent; + return await FixDocumentAsync(nodeWithDiagnostic, document, cancellationToken); + } + public static SyntaxNode IntroduceFieldFromConstructor(SyntaxNode root, ConstructorDeclarationSyntax constructorStatement, ParameterSyntax parameter) { // There are no constructors in interfaces, therefore all types remaining type (class and struct) are fine. diff --git a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProviderAll.cs b/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProviderAll.cs deleted file mode 100644 index 81d29b07e..000000000 --- a/src/CSharp/CodeCracker/Refactoring/IntroduceFieldFromConstructorCodeFixProviderAll.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Linq; -using System.Threading.Tasks; - -namespace CodeCracker.CSharp.Refactoring -{ - public sealed class IntroduceFieldFromConstructorCodeFixAllProvider : FixAllProvider - { - private static readonly SyntaxAnnotation introduceFieldAnnotation = new SyntaxAnnotation(nameof(IntroduceFieldFromConstructorCodeFixAllProvider)); - private IntroduceFieldFromConstructorCodeFixAllProvider() { } - public static readonly IntroduceFieldFromConstructorCodeFixAllProvider Instance = new IntroduceFieldFromConstructorCodeFixAllProvider(); - - public override Task GetFixAsync(FixAllContext fixAllContext) - { - switch (fixAllContext.Scope) - { - case FixAllScope.Document: - return Task.FromResult(CodeAction.Create(IntroduceFieldFromConstructorCodeFixProvider.MessageFormat, - async ct => fixAllContext.Document.WithSyntaxRoot(await GetFixedDocumentAsync(fixAllContext, fixAllContext.Document)))); - case FixAllScope.Project: - return Task.FromResult(CodeAction.Create(IntroduceFieldFromConstructorCodeFixProvider.MessageFormat, - ct => GetFixedProjectAsync(fixAllContext, fixAllContext.Project))); - case FixAllScope.Solution: - return Task.FromResult(CodeAction.Create(IntroduceFieldFromConstructorCodeFixProvider.MessageFormat, - ct => GetFixedSolutionAsync(fixAllContext))); - } - return null; - } - - private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) - { - var newSolution = fixAllContext.Solution; - foreach (var projectId in newSolution.ProjectIds) - newSolution = await GetFixedProjectAsync(fixAllContext, newSolution.GetProject(projectId)).ConfigureAwait(false); - return newSolution; - } - - private async static Task GetFixedProjectAsync(FixAllContext fixAllContext, Project project) - { - var solution = project.Solution; - var newDocuments = project.Documents.ToDictionary(d => d.Id, d => GetFixedDocumentAsync(fixAllContext, d)); - await Task.WhenAll(newDocuments.Values).ConfigureAwait(false); - foreach (var newDoc in newDocuments) - solution = solution.WithDocumentSyntaxRoot(newDoc.Key, newDoc.Value.Result); - return solution; - } - - private async static Task GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) - { - var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); - var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); - var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing); - var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => original.WithAdditionalAnnotations(introduceFieldAnnotation)); - var semanticModel = await document.GetSemanticModelAsync(fixAllContext.CancellationToken).ConfigureAwait(false); - while (true) - { - var annotatedNodes = newRoot.GetAnnotatedNodes(introduceFieldAnnotation); - var node = annotatedNodes.FirstOrDefault(); - if (node == null) break; - - var constructorMethod = (ConstructorDeclarationSyntax)node.Parent.Parent; - var parameter = (ParameterSyntax)node; - newRoot = IntroduceFieldFromConstructorCodeFixProvider.IntroduceFieldFromConstructor(newRoot, constructorMethod, parameter); - node = newRoot.GetAnnotatedNodes(introduceFieldAnnotation).First(); - newRoot = newRoot.ReplaceNode(node, node.WithoutAnnotations(introduceFieldAnnotation)); - } - return newRoot; - } - } -} diff --git a/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs b/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs index 318839da0..17f3ec989 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs +++ b/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs @@ -214,6 +214,51 @@ public static string InconsistentAccessibilityInPropertyType_Title { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Consider introduce field for constructor parameters. ähnelt. + /// + public static string IntroduceFieldFromConstructorAnalyzer_Description { + get { + return ResourceManager.GetString("IntroduceFieldFromConstructorAnalyzer_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Introduce a field for parameter: {0} ähnelt. + /// + public static string IntroduceFieldFromConstructorAnalyzer_MessageFormat { + get { + return ResourceManager.GetString("IntroduceFieldFromConstructorAnalyzer_MessageFormat", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Consider introduce field for constructor parameters. ähnelt. + /// + public static string IntroduceFieldFromConstructorAnalyzer_Title { + get { + return ResourceManager.GetString("IntroduceFieldFromConstructorAnalyzer_Title", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Introduce field: {0} from constructor. ähnelt. + /// + public static string IntroduceFieldFromConstructorCodeFixProvider_MessageFormat { + get { + return ResourceManager.GetString("IntroduceFieldFromConstructorCodeFixProvider_MessageFormat", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Introduce fields for constructor parameters. ähnelt. + /// + public static string IntroduceFieldFromConstructorCodeFixProvider_Title { + get { + return ResourceManager.GetString("IntroduceFieldFromConstructorCodeFixProvider_Title", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Make method non async ähnelt. /// diff --git a/src/Common/CodeCracker.Common/Properties/Resources.resx b/src/Common/CodeCracker.Common/Properties/Resources.resx index accb497bd..aab3eb4fd 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.resx +++ b/src/Common/CodeCracker.Common/Properties/Resources.resx @@ -228,4 +228,19 @@ Simplify by using an getter-only auto-property + + Consider introduce field for constructor parameters. + + + Introduce a field for parameter: {0} + + + Consider introduce field for constructor parameters. + + + Introduce field: {0} from constructor. + + + Introduce fields for constructor parameters. + \ No newline at end of file From 7d7391c3c8ece06feaeb4910077fa649edcf9e09 Mon Sep 17 00:00:00 2001 From: Martin Strecker Date: Wed, 28 Jun 2017 01:53:17 +0200 Subject: [PATCH 169/234] Added support for constructors in UseInvokeMethodToFireEventAnalyzer From #942. --- .../UseInvokeMethodToFireEventAnalyzer.cs | 2 +- .../Design/UseInvokeMethodToFireEventTests.cs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs index 1ae8992d4..6a30e2533 100644 --- a/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/UseInvokeMethodToFireEventAnalyzer.cs @@ -62,7 +62,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) private static bool HasCheckForNullThatReturns(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) { - var method = invocation.FirstAncestorOfKind(SyntaxKind.MethodDeclaration) as MethodDeclarationSyntax; + var method = invocation.FirstAncestorOfKind(SyntaxKind.MethodDeclaration, SyntaxKind.ConstructorDeclaration) as BaseMethodDeclarationSyntax; if (method != null && method.Body != null) { var ifs = method.Body.Statements.OfKind(SyntaxKind.IfStatement); diff --git a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs index 0ff013093..f392107bc 100644 --- a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs @@ -1134,6 +1134,23 @@ public void Bar() { var b = _filter != null && _filter(); } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(test.WrapInCSharpClass()); + } + + [Fact] + public async void IgnoreIfInConstructorAndThatCheckedForNotNull() + { + //https://github.com/code-cracker/code-cracker/issues/926 + const string test = @" +public class Foo +{ + public Foo(System.Action action) + { + if (action == null) + throw new System.ArgumentNullException(); + action(); + } }"; await VerifyCSharpHasNoDiagnosticsAsync(test.WrapInCSharpClass()); } From 4f5cd46f8e61009c5ae7cd6a91506bf1b6e81d3e Mon Sep 17 00:00:00 2001 From: baks Date: Thu, 31 Mar 2016 21:13:45 +0200 Subject: [PATCH 170/234] PropertyChangedEventArgs unnecessary allocation CodeFix provider & analyzer --- src/CSharp/CodeCracker/CodeCracker.csproj | 2 + ...dEventArgsUnnecessaryAllocationAnalyzer.cs | 244 ++++++++++++++ ...rgsUnnecessaryAllocationCodeFixProvider.cs | 93 +++++ src/Common/CodeCracker.Common/DiagnosticId.cs | 1 + .../Properties/Resources.Designer.cs | 144 +++++--- .../Properties/Resources.fr.resx | 12 + .../Properties/Resources.resx | 12 + .../CodeCracker.Test/CodeCracker.Test.csproj | 2 + ...tArgsUnnecessaryAllocationAnalyzerTests.cs | 169 ++++++++++ ...necessaryAllocationCodeFixProviderTests.cs | 318 ++++++++++++++++++ 10 files changed, 943 insertions(+), 54 deletions(-) create mode 100644 src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs create mode 100644 src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs create mode 100644 test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs create mode 100644 test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 715a8f4ac..22c6e50a0 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -69,6 +69,8 @@ + + diff --git a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs new file mode 100644 index 000000000..b1a15bf7f --- /dev/null +++ b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Immutable; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +using static Microsoft.CodeAnalysis.CSharp.SyntaxFacts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static Microsoft.CodeAnalysis.CSharp.SyntaxKind; + +namespace CodeCracker.CSharp.Refactoring +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class PropertyChangedEventArgsUnnecessaryAllocationAnalyzer : DiagnosticAnalyzer + { + private const string PropertyChangedEventArgsClassName = "PropertyChangedEventArgs"; + + internal const string Category = SupportedCategories.Refactoring; + + private static readonly IdentifierExtractor ExtractIdentifier = new IdentifierExtractor(); + private static readonly IsArgumentALiteralOrNameof IsAnyArgumentLiteralOrNameof = new IsArgumentALiteralOrNameof(); + + internal static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.PropertyChangedEventArgsUnnecessaryAllocation_Title), Resources.ResourceManager, typeof(Resources)); + internal static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.PropertyChangedEventArgsUnnecessaryAllocation_Description), Resources.ResourceManager, typeof(Resources)); + internal static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.PropertyChangedEventArgsUnnecessaryAllocation_MessageFormat), Resources.ResourceManager, typeof(Resources)); + + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId(), + Title, + MessageFormat, + Category, + DiagnosticSeverity.Hidden, + isEnabledByDefault: true, + description: Description, + helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation)); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.RegisterSyntaxNodeAction(LanguageVersion.CSharp6, PropertyChangedCreation, SyntaxKind.ObjectCreationExpression); + } + + private static void PropertyChangedCreation(SyntaxNodeAnalysisContext context) + { + var propertyChangedEventArgsCreationExpr = (ObjectCreationExpressionSyntax) context.Node; + var identifier = propertyChangedEventArgsCreationExpr.Type.Accept(ExtractIdentifier); + if (ShouldReportDiagnostic(propertyChangedEventArgsCreationExpr, identifier.ValueText)) + { + var data = new PropertyChangedEventArgsAnalyzerData(propertyChangedEventArgsCreationExpr); + + context.ReportDiagnostic(Diagnostic.Create(Rule, propertyChangedEventArgsCreationExpr.GetLocation(), data.ToDiagnosticProperties())); + } + } + + private static bool ShouldReportDiagnostic(ObjectCreationExpressionSyntax propertyChangedExpr, + string identifierName) => + IsPropertyChangedEventArgs(identifierName) + && propertyChangedExpr.ArgumentList.Accept(IsAnyArgumentLiteralOrNameof) + && !IsAlreadyStatic(propertyChangedExpr); + + private static bool IsPropertyChangedEventArgs(string s) + => string.Equals(PropertyChangedEventArgsClassName, s, StringComparison.Ordinal); + + private static bool IsAlreadyStatic(ObjectCreationExpressionSyntax objectCreationExpr) + { + var result = false; + var memberForObjectCreationExpr = objectCreationExpr.FirstAncestorOrSelfThatIsAMember(); + switch (memberForObjectCreationExpr.Kind()) + { + case SyntaxKind.ConstructorDeclaration: + var constructorDeclaration = (ConstructorDeclarationSyntax) memberForObjectCreationExpr; + result = ContainsStaticModifier(constructorDeclaration.Modifiers); + break; + case SyntaxKind.FieldDeclaration: + var fieldDeclaration = (FieldDeclarationSyntax)memberForObjectCreationExpr; + result = ContainsStaticModifier(fieldDeclaration.Modifiers); + break; + } + return result; + } + + private static bool ContainsStaticModifier(SyntaxTokenList modifiers) => modifiers.Any(StaticKeyword); + + private class IdentifierExtractor : CSharpSyntaxVisitor + { + public override SyntaxToken VisitIdentifierName(IdentifierNameSyntax node) => node.Identifier; + public override SyntaxToken VisitQualifiedName(QualifiedNameSyntax node) => VisitIdentifierName((IdentifierNameSyntax)node.Right); + } + + private class IsArgumentALiteralOrNameof : CSharpSyntaxVisitor + { + public override bool VisitArgumentList(ArgumentListSyntax node) => node.Arguments.Any(arg => arg.Accept(this)); + public override bool VisitArgument(ArgumentSyntax node) => node.Expression.Accept(this); + public override bool VisitLiteralExpression(LiteralExpressionSyntax node) => true; + + public override bool VisitIdentifierName(IdentifierNameSyntax node) + => string.Equals("nameof", node.Identifier.ValueText, StringComparison.Ordinal); + + public override bool VisitInvocationExpression(InvocationExpressionSyntax node) => node.Expression.Accept(this); + } + } + + public class PropertyChangedEventArgsAnalyzerData + { + private const string ArgumentKeyName = "Argument"; + private const string IsNullKeyName = "IsNull"; + private const string IsNameofKeyName = "NameOf"; + private const string TypeKeyName = "Type"; + private const string SuffixAllProperties = "AllProperties"; + + public readonly string FullTypeName; + public readonly string ArgumentName; + public readonly bool ArgumentIsNullLiteral; + public readonly bool ArgumentIsNameofExpression; + public readonly string StaticFieldIdentifierNameProposition; + + private PropertyChangedEventArgsAnalyzerData(string fullTypeName, string argumentName, string isNullLiteral, string isNameof) + { + this.FullTypeName = fullTypeName; + this.ArgumentName = argumentName ?? string.Empty; + this.ArgumentIsNullLiteral = bool.Parse(isNullLiteral); + this.ArgumentIsNameofExpression = bool.Parse(isNameof); + + this.StaticFieldIdentifierNameProposition = $"PropertyChangedEventArgsFor{SuffixForStaticInstance()}"; + } + + public PropertyChangedEventArgsAnalyzerData(ObjectCreationExpressionSyntax propertyChangedInstanceCreationExpr) + { + if (propertyChangedInstanceCreationExpr == null) + { + throw new ArgumentNullException(nameof(propertyChangedInstanceCreationExpr)); + } + + var analyzer = new PropertyChangedCreationSyntaxAnalyzer(); + propertyChangedInstanceCreationExpr.ArgumentList.Accept(analyzer); + + this.FullTypeName = propertyChangedInstanceCreationExpr.Type.ToString(); + this.ArgumentName = analyzer.IdentifierName; + this.ArgumentIsNullLiteral = analyzer.NullLiteralExpressionFound; + this.ArgumentIsNameofExpression = analyzer.NameofExpressionFound; + } + + public string StaticFieldIdentifierName(IEnumerable nameHints) => nameHints.Contains(StaticFieldIdentifierNameProposition) ? + CreateNewIdenfitierName(StaticFieldIdentifierNameProposition, 1, nameHints) : StaticFieldIdentifierNameProposition; + + public MemberDeclarationSyntax PropertyChangedEventArgsStaticField(IEnumerable nameHints) + { + return FieldDeclaration(List(), + TokenList(Token(PrivateKeyword), Token(StaticKeyword), Token(ReadOnlyKeyword)), + VariableDeclaration(FieldType(FullTypeName), VariableName(StaticFieldIdentifierName(nameHints)))); + } + + public ImmutableDictionary ToDiagnosticProperties() + { + var dict = ImmutableDictionary.CreateBuilder(); + + dict.Add(ArgumentKeyName, ArgumentName); + dict.Add(IsNullKeyName, ArgumentIsNullLiteral.ToString()); + dict.Add(IsNameofKeyName, ArgumentIsNameofExpression.ToString()); + dict.Add(TypeKeyName, FullTypeName); + + return dict.ToImmutable(); + } + + public static PropertyChangedEventArgsAnalyzerData FromDiagnosticProperties(ImmutableDictionary properties) + { + return new PropertyChangedEventArgsAnalyzerData( + properties[TypeKeyName], properties[ArgumentKeyName], properties[IsNullKeyName], properties[IsNameofKeyName]); + } + + private EqualsValueClauseSyntax PropertyChangedEventArgsInstance() => + EqualsValueClause(Token(EqualsToken), + ObjectCreationExpression(ParseTypeName(FullTypeName), + ArgumentList( + SingletonSeparatedList( + PropertyChangedEventArgsCtorArgument())), default(InitializerExpressionSyntax))); + + private ArgumentSyntax PropertyChangedEventArgsCtorArgument() => + Argument(ArgumentIsNameofExpression + ? ParseExpression($"nameof({ArgumentName})") + : ArgumentIsNullLiteral ? LiteralExpression(NullLiteralExpression) : StringLiteral(ArgumentName)); + + private string SuffixForStaticInstance() + { + return ArgumentIsNullLiteral || ArgumentNameIsStar() ? SuffixAllProperties : MakeValidIdentifier(ArgumentName); + } + + private SeparatedSyntaxList VariableName(string fieldName) => + SeparatedList(new[] + { + VariableDeclarator(fieldName) + .WithInitializer(PropertyChangedEventArgsInstance()) + }); + + private bool ArgumentNameIsStar() => string.Equals(ArgumentName, "*", StringComparison.OrdinalIgnoreCase); + + private static string MakeValidIdentifier(string s) => IsValidIdentifier(s) ? s : SanitizeIdentifierName(s); + + private static string SanitizeIdentifierName(string s) => s.ToCharArray() + .Aggregate(new StringBuilder(), + (sanitized, nextChar) => IsValidIdentifier($"{sanitized.ToString()}{nextChar}") ? sanitized.Append(nextChar) : sanitized) + .ToString(); + + private static LiteralExpressionSyntax StringLiteral(string s) => LiteralExpression(StringLiteralExpression, Literal(s)); + + private static IdentifierNameSyntax FieldType(string type) => IdentifierName(type); + + private static string CreateNewIdenfitierName(string oldName, int extension, IEnumerable nameHints) + { + var number = int.Parse(new string(oldName.ToCharArray().Reverse().TakeWhile(char.IsNumber).DefaultIfEmpty('0').ToArray())); + var proposition = $"{oldName}{number+extension}"; + return nameHints.Contains(proposition) ? CreateNewIdenfitierName(oldName, extension+1, nameHints) : proposition; + } + + private class PropertyChangedCreationSyntaxAnalyzer : CSharpSyntaxWalker + { + public bool NullLiteralExpressionFound { get; private set; } + public bool NameofExpressionFound { get; private set; } + public string IdentifierName { get; private set; } + + public override void VisitLiteralExpression(LiteralExpressionSyntax node) + { + NameofExpressionFound = false; + NullLiteralExpressionFound = node.IsKind(NullLiteralExpression); + IdentifierName = node.Token.ValueText; + } + + public override void VisitInvocationExpression(InvocationExpressionSyntax node) + { + NameofExpressionFound = true; + base.VisitInvocationExpression(node); + } + + public override void VisitIdentifierName(IdentifierNameSyntax node) => IdentifierName = node.Identifier.ValueText; + } + } +} \ No newline at end of file diff --git a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs new file mode 100644 index 000000000..f0defd319 --- /dev/null +++ b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs @@ -0,0 +1,93 @@ +using System.Collections.Immutable; +using System.Collections.Generic; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using CodeCracker.Properties; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Text; + +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace CodeCracker.CSharp.Refactoring +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider)), Shared] + public sealed class PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider : CodeFixProvider + { + public LocalizableString CodeActionTitle = new LocalizableResourceString(nameof(Resources.PropertyChangedEventArgsUnnecessaryAllocation_CodeActionTitle), Resources.ResourceManager, typeof(Resources)); + + public override ImmutableArray FixableDiagnosticIds + => ImmutableArray.Create(DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId()); + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var diagnostic = context.Diagnostics.First(); + context.RegisterCodeFix( + CodeAction.Create(CodeActionTitle.ToString(), + token => ChangePropertyChangedEventArgsToStatic(context.Document, diagnostic.Location, diagnostic.Properties, token), + nameof(PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider)), diagnostic); + + return Task.FromResult(true); + } + + private static async Task ChangePropertyChangedEventArgsToStatic(Document document, Location location, + ImmutableDictionary properties, CancellationToken cancellationToken) + { + var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken); + var data = PropertyChangedEventArgsAnalyzerData.FromDiagnosticProperties(properties); + + var newSyntaxRoot = new PropertyChangedUnnecessaryAllocationRewriter(data, location.SourceSpan).Visit(syntaxRoot); + + return document.WithSyntaxRoot(newSyntaxRoot); + } + + private class PropertyChangedUnnecessaryAllocationRewriter : CSharpSyntaxRewriter + { + private readonly PropertyChangedEventArgsAnalyzerData ContextData; + private readonly TextSpan DiagnosticLocation; + + private bool DiagnosticLocationFound = false; + private IEnumerable nameHints; + + public PropertyChangedUnnecessaryAllocationRewriter(PropertyChangedEventArgsAnalyzerData contextData, TextSpan diagnosticLocation) + { + this.ContextData = contextData; + this.DiagnosticLocation = diagnosticLocation; + } + + public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) + { + nameHints = node.Members.OfType() + .SelectMany(fd => fd.Declaration.Variables.Select(vds => vds.Identifier.ValueText)); + + var traverseResult = base.VisitClassDeclaration(node) as ClassDeclarationSyntax; + var result = DiagnosticLocationFound ? AddPropertyChangedEventArgsStaticField(traverseResult, nameHints ?? Enumerable.Empty()) : traverseResult; + DiagnosticLocationFound = false; + return result; + } + + public override SyntaxNode VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) + { + if(node.Span == DiagnosticLocation) + { + DiagnosticLocationFound = true; + + return ParseExpression(ContextData.StaticFieldIdentifierName(nameHints ?? Enumerable.Empty())) + .WithLeadingTrivia(node.GetLeadingTrivia()) + .WithTrailingTrivia(node.GetTrailingTrivia()); + } + return base.VisitObjectCreationExpression(node); + } + + private ClassDeclarationSyntax AddPropertyChangedEventArgsStaticField(ClassDeclarationSyntax declaration, IEnumerable nameHints) => declaration + .WithMembers(declaration.Members.Insert(0, ContextData.PropertyChangedEventArgsStaticField(nameHints).WithAdditionalAnnotations(Formatter.Annotation))); + } + } +} diff --git a/src/Common/CodeCracker.Common/DiagnosticId.cs b/src/Common/CodeCracker.Common/DiagnosticId.cs index 28feee0f8..4dfc7ecb6 100644 --- a/src/Common/CodeCracker.Common/DiagnosticId.cs +++ b/src/Common/CodeCracker.Common/DiagnosticId.cs @@ -80,6 +80,7 @@ public enum DiagnosticId NameOf_External = 108, StringFormatArgs_ExtraArgs = 111, AlwaysUseVarOnPrimitives = 105, + PropertyChangedEventArgsUnnecessaryAllocation = 106, UnnecessaryToStringInStringConcatenation = 118, SwitchCaseWithoutDefault = 120, ReadOnlyComplexTypes = 121, diff --git a/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs b/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs index 17f3ec989..af567f32d 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs +++ b/src/Common/CodeCracker.Common/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -14,12 +14,12 @@ namespace CodeCracker.Properties { /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -34,7 +34,7 @@ internal Resources() { } /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -48,8 +48,8 @@ internal Resources() { } /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -62,7 +62,7 @@ internal Resources() { } /// - /// Sucht eine lokalisierte Zeichenfolge, die String interpolation allows for better reading of the resulting string when compared to Console.WriteLine arguments. You should use Console.WriteLine with arguments only when another method is supplying the format string. ähnelt. + /// Looks up a localized string similar to String interpolation allows for better reading of the resulting string when compared to Console.WriteLine arguments. You should use Console.WriteLine with arguments only when another method is supplying the format string.. /// public static string ConsoleWriteLineAnalyzer_Description { get { @@ -71,7 +71,7 @@ public static string ConsoleWriteLineAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation ähnelt. + /// Looks up a localized string similar to Use string interpolation. /// public static string ConsoleWriteLineAnalyzer_MessageFormat { get { @@ -80,7 +80,7 @@ public static string ConsoleWriteLineAnalyzer_MessageFormat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation instead of arguments on Console.WriteLine ähnelt. + /// Looks up a localized string similar to Use string interpolation instead of arguments on Console.WriteLine. /// public static string ConsoleWriteLineAnalyzer_Title { get { @@ -89,7 +89,7 @@ public static string ConsoleWriteLineAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change to string interpolation ähnelt. + /// Looks up a localized string similar to Change to string interpolation. /// public static string ConsoleWriteLineCodeFixProvider_Title { get { @@ -98,7 +98,7 @@ public static string ConsoleWriteLineCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die An empty catch block suppress all errors and shouldn't be used.\r\nIf the error is expected consider logging it or changing the control flow such that it is explicit. ähnelt. + /// Looks up a localized string similar to An empty catch block suppress all errors and shouldn't be used.\r\nIf the error is expected consider logging it or changing the control flow such that it is explicit.. /// public static string EmptyCatchBlockAnalyzer_Description { get { @@ -107,7 +107,7 @@ public static string EmptyCatchBlockAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Empty Catch Block. ähnelt. + /// Looks up a localized string similar to Empty Catch Block.. /// public static string EmptyCatchBlockAnalyzer_Message { get { @@ -116,7 +116,7 @@ public static string EmptyCatchBlockAnalyzer_Message { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Catch block cannot be empty ähnelt. + /// Looks up a localized string similar to Catch block cannot be empty. /// public static string EmptyCatchBlockAnalyzer_Title { get { @@ -125,7 +125,7 @@ public static string EmptyCatchBlockAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Insert Exception class to Catch ähnelt. + /// Looks up a localized string similar to Insert Exception class to Catch. /// public static string EmptyCatchBlockCodeFixProvider_InsertException { get { @@ -134,7 +134,7 @@ public static string EmptyCatchBlockCodeFixProvider_InsertException { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Remove Empty Catch Block ähnelt. + /// Looks up a localized string similar to Remove Empty Catch Block. /// public static string EmptyCatchBlockCodeFixProvider_Remove { get { @@ -143,7 +143,7 @@ public static string EmptyCatchBlockCodeFixProvider_Remove { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Remove Empty Catch Block and Put a Documentation Link about Try...Catch use ähnelt. + /// Looks up a localized string similar to Remove Empty Catch Block and Put a Documentation Link about Try...Catch use. /// public static string EmptyCatchBlockCodeFixProvider_RemoveAndDocumentation { get { @@ -152,7 +152,7 @@ public static string EmptyCatchBlockCodeFixProvider_RemoveAndDocumentation { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Remove wrapping Try Block ähnelt. + /// Looks up a localized string similar to Remove wrapping Try Block. /// public static string EmptyCatchBlockCodeFixProvider_RemoveTry { get { @@ -161,7 +161,7 @@ public static string EmptyCatchBlockCodeFixProvider_RemoveTry { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change field type '{0}' accessibility to be as accessible as field '{1}' ähnelt. + /// Looks up a localized string similar to Change field type '{0}' accessibility to be as accessible as field '{1}'. /// public static string InconsistentAccessibilityInFieldType_Title { get { @@ -170,7 +170,7 @@ public static string InconsistentAccessibilityInFieldType_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change parameter type '{0}' accessibility to be as accessible as indexer 'this[{1}]' ähnelt. + /// Looks up a localized string similar to Change parameter type '{0}' accessibility to be as accessible as indexer 'this[{1}]'. /// public static string InconsistentAccessibilityInIndexerParameter_Title { get { @@ -179,7 +179,7 @@ public static string InconsistentAccessibilityInIndexerParameter_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change indexer return type '{0}' accessibility to be as accessible as indexer 'this[{1}]' ähnelt. + /// Looks up a localized string similar to Change indexer return type '{0}' accessibility to be as accessible as indexer 'this[{1}]'. /// public static string InconsistentAccessibilityInIndexerReturnType_Title { get { @@ -188,7 +188,7 @@ public static string InconsistentAccessibilityInIndexerReturnType_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change parameter type '{0}' accessibility to be as accessible as method '{1}' ähnelt. + /// Looks up a localized string similar to Change parameter type '{0}' accessibility to be as accessible as method '{1}'. /// public static string InconsistentAccessibilityInMethodParameter_Title { get { @@ -197,7 +197,7 @@ public static string InconsistentAccessibilityInMethodParameter_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change return type '{0}' accessibility to be as accessible as method '{1}' ähnelt. + /// Looks up a localized string similar to Change return type '{0}' accessibility to be as accessible as method '{1}'. /// public static string InconsistentAccessibilityInMethodReturnType_Title { get { @@ -206,7 +206,7 @@ public static string InconsistentAccessibilityInMethodReturnType_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change property type '{0}' accessibility to be as accessible as property '{1}' ähnelt. + /// Looks up a localized string similar to Change property type '{0}' accessibility to be as accessible as property '{1}'. /// public static string InconsistentAccessibilityInPropertyType_Title { get { @@ -215,7 +215,7 @@ public static string InconsistentAccessibilityInPropertyType_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Consider introduce field for constructor parameters. ähnelt. + /// Looks up a localized string similar to Consider introduce field for constructor parameters.. /// public static string IntroduceFieldFromConstructorAnalyzer_Description { get { @@ -224,7 +224,7 @@ public static string IntroduceFieldFromConstructorAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Introduce a field for parameter: {0} ähnelt. + /// Looks up a localized string similar to Introduce a field for parameter: {0}. /// public static string IntroduceFieldFromConstructorAnalyzer_MessageFormat { get { @@ -233,7 +233,7 @@ public static string IntroduceFieldFromConstructorAnalyzer_MessageFormat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Consider introduce field for constructor parameters. ähnelt. + /// Looks up a localized string similar to Consider introduce field for constructor parameters.. /// public static string IntroduceFieldFromConstructorAnalyzer_Title { get { @@ -242,7 +242,7 @@ public static string IntroduceFieldFromConstructorAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Introduce field: {0} from constructor. ähnelt. + /// Looks up a localized string similar to Introduce field: {0} from constructor.. /// public static string IntroduceFieldFromConstructorCodeFixProvider_MessageFormat { get { @@ -251,7 +251,7 @@ public static string IntroduceFieldFromConstructorCodeFixProvider_MessageFormat } /// - /// Sucht eine lokalisierte Zeichenfolge, die Introduce fields for constructor parameters. ähnelt. + /// Looks up a localized string similar to Introduce fields for constructor parameters.. /// public static string IntroduceFieldFromConstructorCodeFixProvider_Title { get { @@ -260,7 +260,7 @@ public static string IntroduceFieldFromConstructorCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Make method non async ähnelt. + /// Looks up a localized string similar to Make method non async. /// public static string MakeMethodNonAsyncCodeFixProvider_Title { get { @@ -269,7 +269,7 @@ public static string MakeMethodNonAsyncCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produce code that is easier to refactor. ähnelt. + /// Looks up a localized string similar to In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produce code that is easier to refactor.. /// public static string NameOfAnalyzer_Description { get { @@ -278,7 +278,7 @@ public static string NameOfAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use 'nameof({0})' instead of specifying the program element name. ähnelt. + /// Looks up a localized string similar to Use 'nameof({0})' instead of specifying the program element name.. /// public static string NameOfAnalyzer_MessageFormat { get { @@ -287,7 +287,7 @@ public static string NameOfAnalyzer_MessageFormat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use nameof ähnelt. + /// Looks up a localized string similar to Use nameof. /// public static string NameOfAnalyzer_Title { get { @@ -296,7 +296,7 @@ public static string NameOfAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use nameof() ähnelt. + /// Looks up a localized string similar to Use nameof(). /// public static string NameOfCodeFixProvider_Title { get { @@ -305,7 +305,43 @@ public static string NameOfCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Getter only properties with backing read-only field can be converted to getter-only auto-properties. ähnelt. + /// Looks up a localized string similar to Create static PropertyChangedEventArgs instance and reuse. + /// + public static string PropertyChangedEventArgsUnnecessaryAllocation_CodeActionTitle { + get { + return ResourceManager.GetString("PropertyChangedEventArgsUnnecessaryAllocation_CodeActionTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Creating every time an instance of PropertyChangedEventArgs class causes unnecessary memory allocation. Instance can be created once and reused.. + /// + public static string PropertyChangedEventArgsUnnecessaryAllocation_Description { + get { + return ResourceManager.GetString("PropertyChangedEventArgsUnnecessaryAllocation_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation.. + /// + public static string PropertyChangedEventArgsUnnecessaryAllocation_MessageFormat { + get { + return ResourceManager.GetString("PropertyChangedEventArgsUnnecessaryAllocation_MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PropertyChangedEventArgs unnecessary allocation. + /// + public static string PropertyChangedEventArgsUnnecessaryAllocation_Title { + get { + return ResourceManager.GetString("PropertyChangedEventArgsUnnecessaryAllocation_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Getter only properties with backing read-only field can be converted to getter-only auto-properties.. /// public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_Description { get { @@ -314,7 +350,7 @@ public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Property {0} can be converted to an getter-only auto-property. ähnelt. + /// Looks up a localized string similar to Property {0} can be converted to an getter-only auto-property.. /// public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_MessageFormat { get { @@ -323,7 +359,7 @@ public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_MessageFormat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Property can be simplified by using an getter-only auto-property. ähnelt. + /// Looks up a localized string similar to Property can be simplified by using an getter-only auto-property.. /// public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_Title { get { @@ -332,7 +368,7 @@ public static string ReplaceWithGetterOnlyAutoPropertyAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Simplify by using an getter-only auto-property ähnelt. + /// Looks up a localized string similar to Simplify by using an getter-only auto-property. /// public static string ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title { get { @@ -341,7 +377,7 @@ public static string ReplaceWithGetterOnlyAutoPropertyCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die String interpolation allows for better reading of the resulting string when compared to String.Format. You should use String.Format only when another method is supplying the format string. ähnelt. + /// Looks up a localized string similar to String interpolation allows for better reading of the resulting string when compared to String.Format. You should use String.Format only when another method is supplying the format string.. /// public static string StringFormatAnalyzer_Description { get { @@ -350,7 +386,7 @@ public static string StringFormatAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation ähnelt. + /// Looks up a localized string similar to Use string interpolation. /// public static string StringFormatAnalyzer_MessageFormat { get { @@ -359,7 +395,7 @@ public static string StringFormatAnalyzer_MessageFormat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use string interpolation instead of String.Format ähnelt. + /// Looks up a localized string similar to Use string interpolation instead of String.Format. /// public static string StringFormatAnalyzer_Title { get { @@ -368,7 +404,7 @@ public static string StringFormatAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change to string interpolation ähnelt. + /// Looks up a localized string similar to Change to string interpolation. /// public static string StringFormatCodeFixProvider_Title { get { @@ -377,7 +413,7 @@ public static string StringFormatCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Auto properties offer a more concise way of defining a property. If you are using simple getters and setters you are able to simplify your code with autoproperties. ähnelt. + /// Looks up a localized string similar to Auto properties offer a more concise way of defining a property. If you are using simple getters and setters you are able to simplify your code with autoproperties.. /// public static string SwitchToAutoPropAnalyzer_Description { get { @@ -386,7 +422,7 @@ public static string SwitchToAutoPropAnalyzer_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change {0} to an auto property ähnelt. + /// Looks up a localized string similar to Change {0} to an auto property. /// public static string SwitchToAutoPropAnalyzer_MessageFormat { get { @@ -395,7 +431,7 @@ public static string SwitchToAutoPropAnalyzer_MessageFormat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Use auto property ähnelt. + /// Looks up a localized string similar to Use auto property. /// public static string SwitchToAutoPropAnalyzer_Title { get { @@ -404,7 +440,7 @@ public static string SwitchToAutoPropAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Change to auto property ähnelt. + /// Looks up a localized string similar to Change to auto property. /// public static string SwitchToAutoPropCodeFixProvider_Title { get { @@ -413,7 +449,7 @@ public static string SwitchToAutoPropCodeFixProvider_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die You have missing/unexistent parameters in Xml Docs ähnelt. + /// Looks up a localized string similar to You have missing/unexistent parameters in Xml Docs. /// public static string XmlDocumentationAnalyzer_Title { get { @@ -422,7 +458,7 @@ public static string XmlDocumentationAnalyzer_Title { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Create missing parameters in xml docs ähnelt. + /// Looks up a localized string similar to Create missing parameters in xml docs. /// public static string XmlDocumentationCreateMissingParametersCodeFixProvider_Title { get { @@ -431,7 +467,7 @@ public static string XmlDocumentationCreateMissingParametersCodeFixProvider_Titl } /// - /// Sucht eine lokalisierte Zeichenfolge, die Remove unexistent parameters in xml docs ähnelt. + /// Looks up a localized string similar to Remove unexistent parameters in xml docs. /// public static string XmlDocumentationRemoveNonExistentParametersCodeFixProvider_Title { get { diff --git a/src/Common/CodeCracker.Common/Properties/Resources.fr.resx b/src/Common/CodeCracker.Common/Properties/Resources.fr.resx index a7953b4d6..630db6544 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.fr.resx +++ b/src/Common/CodeCracker.Common/Properties/Resources.fr.resx @@ -214,4 +214,16 @@ Si l'erreur est attendu considérer ajouter du logging ou modifier le flow de co Enlever le block Catch vide et ajouter un lien vers la documentation des bonnes pratiques de Try...Catch + + Creating every time an instance of PropertyChangedEventArgs class causes unnecessary memory allocation. Instance can be created once and reused. + + + Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation. + + + PropertyChangedEventArgs unnecessary allocation + + + Create static PropertyChangedEventArgs instance and reuse + \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/Properties/Resources.resx b/src/Common/CodeCracker.Common/Properties/Resources.resx index aab3eb4fd..944e7b07e 100644 --- a/src/Common/CodeCracker.Common/Properties/Resources.resx +++ b/src/Common/CodeCracker.Common/Properties/Resources.resx @@ -243,4 +243,16 @@ Introduce fields for constructor parameters. + + Creating every time an instance of PropertyChangedEventArgs class causes unnecessary memory allocation. Instance can be created once and reused. + + + Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation. + + + PropertyChangedEventArgs unnecessary allocation + + + Create static PropertyChangedEventArgs instance and reuse + \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index c45a93ec6..902abbd5b 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -130,6 +130,8 @@ + + diff --git a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs new file mode 100644 index 000000000..a5707fa68 --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs @@ -0,0 +1,169 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using CodeCracker.CSharp.Refactoring; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Xunit; + +namespace CodeCracker.Test.CSharp.Refactoring +{ + public class PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests : CodeFixVerifier + { + public static IEnumerable SharedData + { + get + { + yield return new[] {"\"Name\""}; + yield return new[] {"nameof(Name)"}; + yield return new[] {"null"}; + } + } + + [Fact] + public async Task DoesNotTriggerDiagnosticWithEmptySourceCodeAsync() + { + const string source = @""; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreation(string ctorArg) + { + var source = $"var args = new PropertyChangedEventArgs({ctorArg})"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 12)); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInMethodInvocation(string ctorArg) + { + var source = $@" +public class Test +{{ + public void TestMethod() + {{ + PropertyChanged(new PropertyChangedEventArgs({ctorArg})) + }} +}}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(6, 25)); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInObjectInitializer(string ctorArg) + { + var source = $"object args = new {{ Name = new PropertyChangedEventArgs({ctorArg}) }}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 28)); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesNotTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInFieldAssignmentWhenFieldIsStatic(string ctorArg) + { + var source = $@" +public class Test +{{ + private static PropertyChangedEventArgs field = new PropertyChangedEventArgs({ctorArg}); +}}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DoesNotTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInStaticConstructor() + { + const string source = @" +public class Test +{ + private static PropertyChangedEventArgs field; + + static Test() + { + field = new PropertyChangedEventArgs(""Name""); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DoesNotTriggerDiagnosticAtObjectInstanceCreation() + { + const string source = @" +public class Test +{ + private object field = new object(); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DoesTriggerDiagnosticAtObjectInstanceCreationUsingQualifiedName() + { + const string source = @" +public class Test +{ + private object field = new System.ComponentModel.PropertyChangedEventArgs(null); +}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(4,28)); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesTriggerDiagnosticInLambdaExpression(string ctorArg) + { + var source = $@" +using System; +using System.ComponentModel; +public class Test +{{ + private PropertyChangedEventArgs field; + + public Test() + {{ + Action action = () => field = new PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(10,39)); + } + + [Fact] + public async Task DoesNotTriggerWhenArgumentIsNotLiteral() + { + var source = $@" +public class Test +{{ + public void TestMethod(string propertyName) + {{ + PropertyChanged(new PropertyChangedEventArgs(propertyName)) + }} +}}"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() + { + return new PropertyChangedEventArgsUnnecessaryAllocationAnalyzer(); + } + + public static DiagnosticResult PropertyChangedUnnecessaryAllocationDiagnostic(int line, int column) + { + return new DiagnosticResult + { + Id = DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId(), + Message = "Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation.", + Severity = DiagnosticSeverity.Hidden, + Locations = new[] + { + new DiagnosticResultLocation("Test0.cs", line, column), + } + }; + } + } +} diff --git a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs new file mode 100644 index 000000000..f9a9ae410 --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs @@ -0,0 +1,318 @@ +using CodeCracker.CSharp.Refactoring; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; + +namespace CodeCracker.Test.CSharp.Refactoring +{ + public class PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests : + CodeFixVerifier + + { + public static IEnumerable SharedData + { + get + { + yield return new[] { "\"Name\"", "Name" }; + yield return new[] { "nameof(Name)", "Name" }; + yield return new[] { "null", "AllProperties" }; + yield return new[] { "\"*\"", "AllProperties" }; + yield return new[] { "\"Name-\"", "Name" }; + } + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task ChangesPropertyChangedEventArgsInstanceToUseStaticField(string ctorArg, string fieldSuffix) + { + var source = $@" +using System.ComponentModel; +public class TestClass +{{ + public string Name {{ get;set; }} + + public void Foo() + {{ + var args = new PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + var fixedCode = $@" +using System.ComponentModel; +public class TestClass +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + + public string Name {{ get;set; }} + + public void Foo() + {{ + var args = PropertyChangedEventArgsFor{fieldSuffix}; + }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesFixWhenEventArgsUsedInMethodInvocation(string ctorArg, string fieldSuffix) + { + var source = $@" +using System.ComponentModel; +public class TestClass +{{ + public string Name {{ get;set; }} + + public void Foo() + {{ + On(new PropertyChangedEventArgs({ctorArg})); + }} + + public void On(PropertyChangedEventArgs args) {{ }} +}}"; + + var fixedCode = $@" +using System.ComponentModel; +public class TestClass +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + + public string Name {{ get;set; }} + + public void Foo() + {{ + On(PropertyChangedEventArgsFor{fieldSuffix}); + }} + + public void On(PropertyChangedEventArgs args) {{ }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task HandlesMultipleClassDeclarations(string ctorArg, string fieldSuffix) + { + var source = $@" +using System.ComponentModel; +public class TestClass +{{ + public string Name {{ get;set; }} + + public void Foo() + {{ + var args = new PropertyChangedEventArgs({ctorArg}); + }} +}} + +public class TestClass2 +{{ +}}"; + + var fixedCode = $@" +using System.ComponentModel; +public class TestClass +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + + public string Name {{ get;set; }} + + public void Foo() + {{ + var args = PropertyChangedEventArgsFor{fieldSuffix}; + }} +}} + +public class TestClass2 +{{ +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesFixWhenQualifiedNameUsed(string ctorArg, string fieldSuffix) + { + var source = $@" +public class TestClass +{{ + public string Name {{ get;set; }} + + public void Foo() + {{ + var args = new System.ComponentModel.PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + var fixedCode = $@" +public class TestClass +{{ + private static readonly System.ComponentModel.PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new System.ComponentModel.PropertyChangedEventArgs({ctorArg}); + + public string Name {{ get;set; }} + + public void Foo() + {{ + var args = PropertyChangedEventArgsFor{fieldSuffix}; + }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode, allowNewCompilerDiagnostics: true); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesFixWhenEventArgsCreatedInField(string ctorArg, string fieldSuffix) + { + var source = $@" +using System.ComponentModel; +public class TestClass +{{ + private PropertyChangedEventArgs field = new PropertyChangedEventArgs({ctorArg}); +}}"; + + var fixedCode = $@" +using System.ComponentModel; +public class TestClass +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + private PropertyChangedEventArgs field = PropertyChangedEventArgsFor{fieldSuffix}; +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesFixWhenEventArgsCreatedInObjectInitializer(string ctorArg, string fieldSuffix) + { + var source = $@" +using System.ComponentModel; +public class TestClass +{{ + public string Name {{ get;set; }} + + public void Foo() + {{ + object args = new {{ Name = new PropertyChangedEventArgs({ctorArg}) }}; + }} +}}"; + + var fixedCode = $@" +using System.ComponentModel; +public class TestClass +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + + public string Name {{ get;set; }} + + public void Foo() + {{ + object args = new {{ Name = PropertyChangedEventArgsFor{fieldSuffix} }}; + }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task HandlesNestedClass(string ctorArg, string fieldSuffix) + { + var source = $@" +using System.ComponentModel; +public class OuterClass +{{ + public class TestClass + {{ + private PropertyChangedEventArgs field = new PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + var fixedCode = $@" +using System.ComponentModel; +public class OuterClass +{{ + public class TestClass + {{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + private PropertyChangedEventArgs field = PropertyChangedEventArgsFor{fieldSuffix}; + }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesFixLambdaExpression(string ctorArg, string fieldSuffix) + { + var source = $@" +using System; +using System.ComponentModel; +public class Test +{{ + private PropertyChangedEventArgs field; + + public Test() + {{ + Action action = () => field = new PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + var fixedCode = $@" +using System; +using System.ComponentModel; +public class Test +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + private PropertyChangedEventArgs field; + + public Test() + {{ + Action action = () => field = PropertyChangedEventArgsFor{fieldSuffix}; + }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + + [Theory] + [MemberData(nameof(SharedData))] + public async Task DoesFixWhenFieldNameIsAlreadyUsed(string ctorArg, string fieldSuffix) + { + var source = $@" +using System; +using System.ComponentModel; +public class Test +{{ + private PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix}; + + public Test() + {{ + Action action = () => PropertyChangedEventArgsFor{fieldSuffix} = new PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + var fixedCode = $@" +using System; +using System.ComponentModel; +public class Test +{{ + private static readonly PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix}1 = new PropertyChangedEventArgs({ctorArg}); + private PropertyChangedEventArgs PropertyChangedEventArgsFor{fieldSuffix}; + + public Test() + {{ + Action action = () => PropertyChangedEventArgsFor{fieldSuffix} = PropertyChangedEventArgsFor{fieldSuffix}1; + }} +}}"; + + await VerifyCSharpFixAsync(source, fixedCode); + } + } +} From 40b7e1834fa218cc28c66cc19e0a368f425b5011 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Wed, 28 Jun 2017 18:42:14 -0300 Subject: [PATCH 171/234] Refactor PropertyChangedEventArgsUnnecessaryAllocation --- ...dEventArgsUnnecessaryAllocationAnalyzer.cs | 54 +++--- ...rgsUnnecessaryAllocationCodeFixProvider.cs | 45 ++--- .../CodeCracker.Test/CodeCracker.Test.csproj | 3 +- ...tArgsUnnecessaryAllocationAnalyzerTests.cs | 169 ---------------- ...gedEventArgsUnnecessaryAllocationTests.cs} | 180 ++++++++++++++++-- 5 files changed, 209 insertions(+), 242 deletions(-) delete mode 100644 test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs rename test/CSharp/CodeCracker.Test/Refactoring/{PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs => PropertyChangedEventArgsUnnecessaryAllocationTests.cs} (59%) diff --git a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs index b1a15bf7f..e9924b9d3 100644 --- a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs @@ -1,17 +1,15 @@ -using System; -using System.Collections.Immutable; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using CodeCracker.Properties; +using CodeCracker.Properties; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; - -using static Microsoft.CodeAnalysis.CSharp.SyntaxFacts; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFacts; using static Microsoft.CodeAnalysis.CSharp.SyntaxKind; namespace CodeCracker.CSharp.Refactoring @@ -49,7 +47,7 @@ public override void Initialize(AnalysisContext context) private static void PropertyChangedCreation(SyntaxNodeAnalysisContext context) { - var propertyChangedEventArgsCreationExpr = (ObjectCreationExpressionSyntax) context.Node; + var propertyChangedEventArgsCreationExpr = (ObjectCreationExpressionSyntax)context.Node; var identifier = propertyChangedEventArgsCreationExpr.Type.Accept(ExtractIdentifier); if (ShouldReportDiagnostic(propertyChangedEventArgsCreationExpr, identifier.ValueText)) { @@ -59,14 +57,12 @@ private static void PropertyChangedCreation(SyntaxNodeAnalysisContext context) } } - private static bool ShouldReportDiagnostic(ObjectCreationExpressionSyntax propertyChangedExpr, - string identifierName) => + private static bool ShouldReportDiagnostic(ObjectCreationExpressionSyntax propertyChangedExpr, string identifierName) => IsPropertyChangedEventArgs(identifierName) && propertyChangedExpr.ArgumentList.Accept(IsAnyArgumentLiteralOrNameof) && !IsAlreadyStatic(propertyChangedExpr); - private static bool IsPropertyChangedEventArgs(string s) - => string.Equals(PropertyChangedEventArgsClassName, s, StringComparison.Ordinal); + private static bool IsPropertyChangedEventArgs(string s) => string.Equals(PropertyChangedEventArgsClassName, s, StringComparison.Ordinal); private static bool IsAlreadyStatic(ObjectCreationExpressionSyntax objectCreationExpr) { @@ -75,7 +71,7 @@ private static bool IsAlreadyStatic(ObjectCreationExpressionSyntax objectCreatio switch (memberForObjectCreationExpr.Kind()) { case SyntaxKind.ConstructorDeclaration: - var constructorDeclaration = (ConstructorDeclarationSyntax) memberForObjectCreationExpr; + var constructorDeclaration = (ConstructorDeclarationSyntax)memberForObjectCreationExpr; result = ContainsStaticModifier(constructorDeclaration.Modifiers); break; case SyntaxKind.FieldDeclaration: @@ -123,31 +119,27 @@ public class PropertyChangedEventArgsAnalyzerData private PropertyChangedEventArgsAnalyzerData(string fullTypeName, string argumentName, string isNullLiteral, string isNameof) { - this.FullTypeName = fullTypeName; - this.ArgumentName = argumentName ?? string.Empty; - this.ArgumentIsNullLiteral = bool.Parse(isNullLiteral); - this.ArgumentIsNameofExpression = bool.Parse(isNameof); + FullTypeName = fullTypeName; + ArgumentName = argumentName ?? string.Empty; + ArgumentIsNullLiteral = bool.Parse(isNullLiteral); + ArgumentIsNameofExpression = bool.Parse(isNameof); - this.StaticFieldIdentifierNameProposition = $"PropertyChangedEventArgsFor{SuffixForStaticInstance()}"; + StaticFieldIdentifierNameProposition = $"PropertyChangedEventArgsFor{SuffixForStaticInstance()}"; } public PropertyChangedEventArgsAnalyzerData(ObjectCreationExpressionSyntax propertyChangedInstanceCreationExpr) { if (propertyChangedInstanceCreationExpr == null) - { throw new ArgumentNullException(nameof(propertyChangedInstanceCreationExpr)); - } - var analyzer = new PropertyChangedCreationSyntaxAnalyzer(); propertyChangedInstanceCreationExpr.ArgumentList.Accept(analyzer); - - this.FullTypeName = propertyChangedInstanceCreationExpr.Type.ToString(); - this.ArgumentName = analyzer.IdentifierName; - this.ArgumentIsNullLiteral = analyzer.NullLiteralExpressionFound; - this.ArgumentIsNameofExpression = analyzer.NameofExpressionFound; + FullTypeName = propertyChangedInstanceCreationExpr.Type.ToString(); + ArgumentName = analyzer.IdentifierName; + ArgumentIsNullLiteral = analyzer.NullLiteralExpressionFound; + ArgumentIsNameofExpression = analyzer.NameofExpressionFound; } - public string StaticFieldIdentifierName(IEnumerable nameHints) => nameHints.Contains(StaticFieldIdentifierNameProposition) ? + public string StaticFieldIdentifierName(IEnumerable nameHints) => nameHints.Contains(StaticFieldIdentifierNameProposition) ? CreateNewIdenfitierName(StaticFieldIdentifierNameProposition, 1, nameHints) : StaticFieldIdentifierNameProposition; public MemberDeclarationSyntax PropertyChangedEventArgsStaticField(IEnumerable nameHints) @@ -215,8 +207,8 @@ private static string SanitizeIdentifierName(string s) => s.ToCharArray() private static string CreateNewIdenfitierName(string oldName, int extension, IEnumerable nameHints) { var number = int.Parse(new string(oldName.ToCharArray().Reverse().TakeWhile(char.IsNumber).DefaultIfEmpty('0').ToArray())); - var proposition = $"{oldName}{number+extension}"; - return nameHints.Contains(proposition) ? CreateNewIdenfitierName(oldName, extension+1, nameHints) : proposition; + var proposition = $"{oldName}{number + extension}"; + return nameHints.Contains(proposition) ? CreateNewIdenfitierName(oldName, extension + 1, nameHints) : proposition; } private class PropertyChangedCreationSyntaxAnalyzer : CSharpSyntaxWalker diff --git a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs index f0defd319..834906f67 100644 --- a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider.cs @@ -1,11 +1,4 @@ -using System.Collections.Immutable; -using System.Collections.Generic; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -using CodeCracker.Properties; +using CodeCracker.Properties; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; @@ -13,7 +6,12 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Text; - +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace CodeCracker.CSharp.Refactoring @@ -31,35 +29,32 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) var diagnostic = context.Diagnostics.First(); context.RegisterCodeFix( CodeAction.Create(CodeActionTitle.ToString(), - token => ChangePropertyChangedEventArgsToStatic(context.Document, diagnostic.Location, diagnostic.Properties, token), + token => ChangePropertyChangedEventArgsToStaticAsync(context.Document, diagnostic.Location, diagnostic.Properties, token), nameof(PropertyChangedEventArgsUnnecessaryAllocationCodeFixProvider)), diagnostic); return Task.FromResult(true); } - private static async Task ChangePropertyChangedEventArgsToStatic(Document document, Location location, + private static async Task ChangePropertyChangedEventArgsToStaticAsync(Document document, Location location, ImmutableDictionary properties, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken); var data = PropertyChangedEventArgsAnalyzerData.FromDiagnosticProperties(properties); - var newSyntaxRoot = new PropertyChangedUnnecessaryAllocationRewriter(data, location.SourceSpan).Visit(syntaxRoot); - return document.WithSyntaxRoot(newSyntaxRoot); } private class PropertyChangedUnnecessaryAllocationRewriter : CSharpSyntaxRewriter { - private readonly PropertyChangedEventArgsAnalyzerData ContextData; - private readonly TextSpan DiagnosticLocation; - - private bool DiagnosticLocationFound = false; + private readonly PropertyChangedEventArgsAnalyzerData contextData; + private readonly TextSpan diagnosticLocation; + private bool diagnosticLocationFound; private IEnumerable nameHints; public PropertyChangedUnnecessaryAllocationRewriter(PropertyChangedEventArgsAnalyzerData contextData, TextSpan diagnosticLocation) { - this.ContextData = contextData; - this.DiagnosticLocation = diagnosticLocation; + this.contextData = contextData; + this.diagnosticLocation = diagnosticLocation; } public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) @@ -68,18 +63,18 @@ public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) .SelectMany(fd => fd.Declaration.Variables.Select(vds => vds.Identifier.ValueText)); var traverseResult = base.VisitClassDeclaration(node) as ClassDeclarationSyntax; - var result = DiagnosticLocationFound ? AddPropertyChangedEventArgsStaticField(traverseResult, nameHints ?? Enumerable.Empty()) : traverseResult; - DiagnosticLocationFound = false; + var result = diagnosticLocationFound ? AddPropertyChangedEventArgsStaticField(traverseResult, nameHints ?? Enumerable.Empty()) : traverseResult; + diagnosticLocationFound = false; return result; } public override SyntaxNode VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) { - if(node.Span == DiagnosticLocation) + if(node.Span == diagnosticLocation) { - DiagnosticLocationFound = true; + diagnosticLocationFound = true; - return ParseExpression(ContextData.StaticFieldIdentifierName(nameHints ?? Enumerable.Empty())) + return ParseExpression(contextData.StaticFieldIdentifierName(nameHints ?? Enumerable.Empty())) .WithLeadingTrivia(node.GetLeadingTrivia()) .WithTrailingTrivia(node.GetTrailingTrivia()); } @@ -87,7 +82,7 @@ public override SyntaxNode VisitObjectCreationExpression(ObjectCreationExpressio } private ClassDeclarationSyntax AddPropertyChangedEventArgsStaticField(ClassDeclarationSyntax declaration, IEnumerable nameHints) => declaration - .WithMembers(declaration.Members.Insert(0, ContextData.PropertyChangedEventArgsStaticField(nameHints).WithAdditionalAnnotations(Formatter.Annotation))); + .WithMembers(declaration.Members.Insert(0, contextData.PropertyChangedEventArgsStaticField(nameHints).WithAdditionalAnnotations(Formatter.Annotation))); } } } diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 902abbd5b..dcf1020ca 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -130,8 +130,7 @@ - - + diff --git a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs deleted file mode 100644 index a5707fa68..000000000 --- a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using CodeCracker.CSharp.Refactoring; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using Xunit; - -namespace CodeCracker.Test.CSharp.Refactoring -{ - public class PropertyChangedEventArgsUnnecessaryAllocationAnalyzerTests : CodeFixVerifier - { - public static IEnumerable SharedData - { - get - { - yield return new[] {"\"Name\""}; - yield return new[] {"nameof(Name)"}; - yield return new[] {"null"}; - } - } - - [Fact] - public async Task DoesNotTriggerDiagnosticWithEmptySourceCodeAsync() - { - const string source = @""; - - await VerifyCSharpHasNoDiagnosticsAsync(source); - } - - [Theory] - [MemberData(nameof(SharedData))] - public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreation(string ctorArg) - { - var source = $"var args = new PropertyChangedEventArgs({ctorArg})"; - - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 12)); - } - - [Theory] - [MemberData(nameof(SharedData))] - public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInMethodInvocation(string ctorArg) - { - var source = $@" -public class Test -{{ - public void TestMethod() - {{ - PropertyChanged(new PropertyChangedEventArgs({ctorArg})) - }} -}}"; - - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(6, 25)); - } - - [Theory] - [MemberData(nameof(SharedData))] - public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInObjectInitializer(string ctorArg) - { - var source = $"object args = new {{ Name = new PropertyChangedEventArgs({ctorArg}) }}"; - - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 28)); - } - - [Theory] - [MemberData(nameof(SharedData))] - public async Task DoesNotTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInFieldAssignmentWhenFieldIsStatic(string ctorArg) - { - var source = $@" -public class Test -{{ - private static PropertyChangedEventArgs field = new PropertyChangedEventArgs({ctorArg}); -}}"; - await VerifyCSharpHasNoDiagnosticsAsync(source); - } - - [Fact] - public async Task DoesNotTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInStaticConstructor() - { - const string source = @" -public class Test -{ - private static PropertyChangedEventArgs field; - - static Test() - { - field = new PropertyChangedEventArgs(""Name""); - } -}"; - await VerifyCSharpHasNoDiagnosticsAsync(source); - } - - [Fact] - public async Task DoesNotTriggerDiagnosticAtObjectInstanceCreation() - { - const string source = @" -public class Test -{ - private object field = new object(); -}"; - await VerifyCSharpHasNoDiagnosticsAsync(source); - } - - [Fact] - public async Task DoesTriggerDiagnosticAtObjectInstanceCreationUsingQualifiedName() - { - const string source = @" -public class Test -{ - private object field = new System.ComponentModel.PropertyChangedEventArgs(null); -}"; - - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(4,28)); - } - - [Theory] - [MemberData(nameof(SharedData))] - public async Task DoesTriggerDiagnosticInLambdaExpression(string ctorArg) - { - var source = $@" -using System; -using System.ComponentModel; -public class Test -{{ - private PropertyChangedEventArgs field; - - public Test() - {{ - Action action = () => field = new PropertyChangedEventArgs({ctorArg}); - }} -}}"; - - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(10,39)); - } - - [Fact] - public async Task DoesNotTriggerWhenArgumentIsNotLiteral() - { - var source = $@" -public class Test -{{ - public void TestMethod(string propertyName) - {{ - PropertyChanged(new PropertyChangedEventArgs(propertyName)) - }} -}}"; - - await VerifyCSharpHasNoDiagnosticsAsync(source); - } - - protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() - { - return new PropertyChangedEventArgsUnnecessaryAllocationAnalyzer(); - } - - public static DiagnosticResult PropertyChangedUnnecessaryAllocationDiagnostic(int line, int column) - { - return new DiagnosticResult - { - Id = DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId(), - Message = "Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", line, column), - } - }; - } - } -} diff --git a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs similarity index 59% rename from test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs rename to test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs index f9a9ae410..9e004869e 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs @@ -1,16 +1,166 @@ using CodeCracker.CSharp.Refactoring; +using Microsoft.CodeAnalysis; using System.Collections.Generic; using System.Threading.Tasks; using Xunit; namespace CodeCracker.Test.CSharp.Refactoring { - public class PropertyChangedEventArgsUnnecessaryAllocationCodeFixProviderTests : - CodeFixVerifier - + public class PropertyChangedEventArgsUnnecessaryAllocationTests : CodeFixVerifier { - public static IEnumerable SharedData + public static IEnumerable SharedDataAnalyzer + { + get + { + yield return new[] { "\"Name\"" }; + yield return new[] { "nameof(Name)" }; + yield return new[] { "null" }; + } + } + + [Fact] + public async Task DoesNotTriggerDiagnosticWithEmptySourceCodeAsync() + { + const string source = @""; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Theory] + [MemberData(nameof(SharedDataAnalyzer))] + public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreation(string ctorArg) + { + var source = $"var args = new PropertyChangedEventArgs({ctorArg})"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 12)); + } + + [Theory] + [MemberData(nameof(SharedDataAnalyzer))] + public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInMethodInvocation(string ctorArg) + { + var source = $@" +public class Test +{{ + public void TestMethod() + {{ + PropertyChanged(new PropertyChangedEventArgs({ctorArg})) + }} +}}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(6, 25)); + } + + [Theory] + [MemberData(nameof(SharedDataAnalyzer))] + public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInObjectInitializer(string ctorArg) + { + var source = $"object args = new {{ Name = new PropertyChangedEventArgs({ctorArg}) }}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 28)); + } + + [Theory] + [MemberData(nameof(SharedDataAnalyzer))] + public async Task DoesNotTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInFieldAssignmentWhenFieldIsStatic(string ctorArg) + { + var source = $@" +public class Test +{{ + private static PropertyChangedEventArgs field = new PropertyChangedEventArgs({ctorArg}); +}}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DoesNotTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreationInStaticConstructor() + { + const string source = @" +public class Test +{ + private static PropertyChangedEventArgs field; + + static Test() + { + field = new PropertyChangedEventArgs(""Name""); + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DoesNotTriggerDiagnosticAtObjectInstanceCreation() + { + const string source = @" +public class Test +{ + private object field = new object(); +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + [Fact] + public async Task DoesTriggerDiagnosticAtObjectInstanceCreationUsingQualifiedName() + { + const string source = @" +public class Test +{ + private object field = new System.ComponentModel.PropertyChangedEventArgs(null); +}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(4, 28)); + } + + [Theory] + [MemberData(nameof(SharedDataAnalyzer))] + public async Task DoesTriggerDiagnosticInLambdaExpression(string ctorArg) + { + var source = $@" +using System; +using System.ComponentModel; +public class Test +{{ + private PropertyChangedEventArgs field; + + public Test() + {{ + Action action = () => field = new PropertyChangedEventArgs({ctorArg}); + }} +}}"; + + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(10, 39)); + } + + [Fact] + public async Task DoesNotTriggerWhenArgumentIsNotLiteral() + { + var source = $@" +public class Test +{{ + public void TestMethod(string propertyName) + {{ + PropertyChanged(new PropertyChangedEventArgs(propertyName)) + }} +}}"; + + await VerifyCSharpHasNoDiagnosticsAsync(source); + } + + public static DiagnosticResult PropertyChangedUnnecessaryAllocationDiagnostic(int line, int column) + { + return new DiagnosticResult + { + Id = DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId(), + Message = "Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation.", + Severity = DiagnosticSeverity.Hidden, + Locations = new[] + { + new DiagnosticResultLocation("Test0.cs", line, column), + } + }; + } + + public static IEnumerable SharedDataCodeFix { get { @@ -23,7 +173,7 @@ public static IEnumerable SharedData } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task ChangesPropertyChangedEventArgsInstanceToUseStaticField(string ctorArg, string fieldSuffix) { var source = $@" @@ -56,7 +206,7 @@ public void Foo() } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task DoesFixWhenEventArgsUsedInMethodInvocation(string ctorArg, string fieldSuffix) { var source = $@" @@ -93,7 +243,7 @@ public void On(PropertyChangedEventArgs args) {{ }} } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task HandlesMultipleClassDeclarations(string ctorArg, string fieldSuffix) { var source = $@" @@ -134,7 +284,7 @@ public class TestClass2 } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task DoesFixWhenQualifiedNameUsed(string ctorArg, string fieldSuffix) { var source = $@" @@ -165,7 +315,7 @@ public void Foo() } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task DoesFixWhenEventArgsCreatedInField(string ctorArg, string fieldSuffix) { var source = $@" @@ -187,7 +337,7 @@ public class TestClass } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task DoesFixWhenEventArgsCreatedInObjectInitializer(string ctorArg, string fieldSuffix) { var source = $@" @@ -220,7 +370,7 @@ public void Foo() } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task HandlesNestedClass(string ctorArg, string fieldSuffix) { var source = $@" @@ -248,7 +398,7 @@ public class TestClass } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task DoesFixLambdaExpression(string ctorArg, string fieldSuffix) { var source = $@" @@ -282,7 +432,7 @@ public Test() } [Theory] - [MemberData(nameof(SharedData))] + [MemberData(nameof(SharedDataCodeFix))] public async Task DoesFixWhenFieldNameIsAlreadyUsed(string ctorArg, string fieldSuffix) { var source = $@" @@ -315,4 +465,4 @@ public Test() await VerifyCSharpFixAsync(source, fixedCode); } } -} +} \ No newline at end of file From be103f0c4976446c5eb87b594c7940bf88368722 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Wed, 28 Jun 2017 18:50:16 -0300 Subject: [PATCH 172/234] Finally remove skip from tests --- .../CodeCracker/Style/RemoveCommentedCodeAnalyzer.cs | 2 +- .../CodeCracker.Test/Style/RemoveCommentedCodeTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/RemoveCommentedCodeAnalyzer.cs b/src/CSharp/CodeCracker/Style/RemoveCommentedCodeAnalyzer.cs index d94d0374d..a25c49944 100644 --- a/src/CSharp/CodeCracker/Style/RemoveCommentedCodeAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/RemoveCommentedCodeAnalyzer.cs @@ -52,7 +52,7 @@ private void AnalyzeSingleLineCommentTrivia(SyntaxTreeAnalysisContext context) } } - readonly CSharpParseOptions options = new CSharpParseOptions(documentationMode: DocumentationMode.None);//todo:bring kind: SourceCodeKind.Interactive back, it is not supported at the current release + readonly CSharpParseOptions options = new CSharpParseOptions(documentationMode: DocumentationMode.None, kind: SourceCodeKind.Script); bool CouldBeSourceCode(string source) { source = source.Trim(); diff --git a/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs b/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs index ef4f222db..e21ce8c9a 100644 --- a/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs @@ -21,7 +21,7 @@ public async Task IgnoresRegularComments() await VerifyCSharpHasNoDiagnosticsAsync(test); } - [Fact(Skip ="Skipped until SourceCodeKind.Interactive can be set on CSharpParseOptions on the analyzer.")] + [Fact] public async Task CreateDiagnosticForSingleLineCommentedCode() { var test = @"// a = 10;".WrapInCSharpMethod(); @@ -49,7 +49,7 @@ public async Task RemovesCommentedCodePreservingRegularComments() await VerifyCSharpFixAsync(test, fixtest); } - [Fact(Skip ="Skipped until SourceCodeKind.Interactive can be set on CSharpParseOptions on the analyzer.")] + [Fact] public async Task CreateDiagnosticForMultipleLinesCommentedCode() { var test = @" @@ -68,7 +68,7 @@ public async Task CreateDiagnosticForMultipleLinesCommentedCode() await VerifyCSharpDiagnosticAsync(test, expected); } - [Fact(Skip ="Skipped until SourceCodeKind.Interactive can be set on CSharpParseOptions on the analyzer.")] + [Fact] public async Task RemovesCommentedMultilineCodePreservingRegularComments() { var test = @" @@ -103,7 +103,7 @@ class Foo await VerifyCSharpFixAsync(test, fixtest); } - [Fact(Skip ="Skipped until SourceCodeKind.Interactive can be set on CSharpParseOptions on the analyzer.")] + [Fact] public async Task RemovesNonPerfectIfCommentedCode() { var test = @" From 187501c5fb95fc4a38fc09a7b8fab41a26169264 Mon Sep 17 00:00:00 2001 From: John Ellison Date: Wed, 25 Oct 2017 10:30:28 -0400 Subject: [PATCH 173/234] Minor spelling fix (#950) --- src/CSharp/CodeCracker/Usage/RethrowExceptionAnalyzer.cs | 2 +- test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Usage/RethrowExceptionAnalyzer.cs b/src/CSharp/CodeCracker/Usage/RethrowExceptionAnalyzer.cs index ffb335e6f..cf2376d77 100644 --- a/src/CSharp/CodeCracker/Usage/RethrowExceptionAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/RethrowExceptionAnalyzer.cs @@ -43,7 +43,7 @@ private static void Analyzer(SyntaxNodeAnalysisContext context) if (catchClause == null) return; var catchExSymbol = context.SemanticModel.GetDeclaredSymbol(catchClause.Declaration); if (!catchExSymbol.Equals(exSymbol)) return; - var diagnostic = Diagnostic.Create(Rule, throwStatement.GetLocation(), "Throwing the same exception that was caught will loose the original stack trace."); + var diagnostic = Diagnostic.Create(Rule, throwStatement.GetLocation(), "Throwing the same exception that was caught will lose the original stack trace."); context.ReportDiagnostic(diagnostic); } } diff --git a/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs b/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs index 7dcd8ce82..4bec3f3fd 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs @@ -30,7 +30,7 @@ public async Task WhenThrowingOriginalExceptionAnalyzerCreatesDiagnostic() var expected = new DiagnosticResult { Id = DiagnosticId.RethrowException.ToDiagnosticId(), - Message = "Throwing the same exception that was caught will loose the original stack trace.", + Message = "Throwing the same exception that was caught will lose the original stack trace.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 21) } }; From fc13c29cb2df52fd8f04126be7eb0f52a0f9f859 Mon Sep 17 00:00:00 2001 From: hacking-god <33166103+hacking-god@users.noreply.github.com> Date: Sat, 28 Oct 2017 03:45:36 +0530 Subject: [PATCH 174/234] Documentation Code Cracker An analyzer library for C# and VB that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. There you will find information on how to contribute, our task board, definition of done, definition of ready, etc. Build status Nuget count License Issues open Coverage Status Source Browser This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. Installing You may use CodeCracker in two ways: as an analyzer library that you install with Nuget into your project or as a Visual Studio extension. The way you want to use it depends on the scenario you are working on. You most likely want the Nuget package. If you want the analyzers to work during your build, and generate warnings and errors during the build, also on build servers, then you want to use the Nuget package. The package is available on nuget (C#, VB). If you want to be able to configure which analyzers are being used in your project, and which ones you will ignore, and commit those changes to source control and share with your team, then you also want the Nuget package. To install from Nuget, for the C# version: Install-Package CodeCracker.CSharp Or for the Visual Basic version: Install-Package CodeCracker.VisualBasic Or use the Package Manager in Visual Studio. There is also a version for both named CodeCracker only, but it makes not sense to get it, you should search for the C# or VB version. If you want the alpha builds that build on each push to the repo, add https://www.myget.org/F/codecrackerbuild/ to your nuget feed. We only push complete releases to Nuget.org, and commit builds go to Myget.org. If you want global analyzers that will work on every project you open in Visual Studio, then you want the Extension. Grab the extension at the Visual Studio Extensions Gallery (C#, VB). To build from source: git clone https://github.com/code-cracker/code-cracker.git cd CodeCracker msbuild Then add a reference to CodeCracker.dll from within the Analyzers node inside References, in Visual Studio. SonarQube Plugin CodeCracker has a SonarQube Plugin that can downloaded at Plugins HomePage. --- Documentation | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Documentation diff --git a/Documentation b/Documentation new file mode 100644 index 000000000..bb9c50c19 --- /dev/null +++ b/Documentation @@ -0,0 +1,40 @@ +Code Cracker + +An analyzer library for C# and VB that uses Roslyn to produce refactorings, code analysis, and other niceties. + +Check the official project site on code-cracker.github.io. There you will find information on how to contribute, our task board, definition of done, definition of ready, etc. + +Build status Nuget count License Issues open Coverage Status Source Browser + +This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. + +Installing + +You may use CodeCracker in two ways: as an analyzer library that you install with Nuget into your project or as a Visual Studio extension. The way you want to use it depends on the scenario you are working on. You most likely want the Nuget package. + +If you want the analyzers to work during your build, and generate warnings and errors during the build, also on build servers, then you want to use the Nuget package. The package is available on nuget (C#, VB). If you want to be able to configure which analyzers are being used in your project, and which ones you will ignore, and commit those changes to source control and share with your team, then you also want the Nuget package. + +To install from Nuget, for the C# version: + +Install-Package CodeCracker.CSharp +Or for the Visual Basic version: + +Install-Package CodeCracker.VisualBasic +Or use the Package Manager in Visual Studio. + +There is also a version for both named CodeCracker only, but it makes not sense to get it, you should search for the C# or VB version. + +If you want the alpha builds that build on each push to the repo, add https://www.myget.org/F/codecrackerbuild/ to your nuget feed. We only push complete releases to Nuget.org, and commit builds go to Myget.org. + +If you want global analyzers that will work on every project you open in Visual Studio, then you want the Extension. Grab the extension at the Visual Studio Extensions Gallery (C#, VB). + +To build from source: + +git clone https://github.com/code-cracker/code-cracker.git +cd CodeCracker +msbuild +Then add a reference to CodeCracker.dll from within the Analyzers node inside References, in Visual Studio. + +SonarQube Plugin + +CodeCracker has a SonarQube Plugin that can downloaded at Plugins HomePage. From 464c3d353162e4c08129d0b16188e17888a3b3c6 Mon Sep 17 00:00:00 2001 From: love-ode <33171148+love-ode@users.noreply.github.com> Date: Sat, 28 Oct 2017 11:08:20 +0530 Subject: [PATCH 175/234] Create Readme Hacktoberfest Sign In Sheet 2017! The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! Instruction In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. Git and Pull Request Resources Github The Net Ninja Awesome-Git How to Create a Pull Request Click on the fork on the top to fork this repo. Go to your repo where you forked the project. Hit the clone button on your forked repo and copy the given link. On your terminal / command prompt, type "git clone [put the link here]". Change the index file in the folder. Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" Push the commit. For example, type "git push [remote-name] master". Go back to the original repo. Hit "new pull request" and compare between forks. Confirm the pull request and that's it! --- Create Readme | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Create Readme diff --git a/Create Readme b/Create Readme new file mode 100644 index 000000000..316700cd9 --- /dev/null +++ b/Create Readme @@ -0,0 +1,26 @@ +Hacktoberfest Sign In Sheet 2017! + +The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! + +Instruction + +In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. + +Git and Pull Request Resources + +Github +The Net Ninja +Awesome-Git +How to Create a Pull Request + +Click on the fork on the top to fork this repo. +Go to your repo where you forked the project. +Hit the clone button on your forked repo and copy the given link. +On your terminal / command prompt, type "git clone [put the link here]". +Change the index file in the folder. +Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. +Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" +Push the commit. For example, type "git push [remote-name] master". +Go back to the original repo. +Hit "new pull request" and compare between forks. +Confirm the pull request and that's it! From aac3be2efb548261641f770482403369c3991525 Mon Sep 17 00:00:00 2001 From: likeme <33179335+likeme@users.noreply.github.com> Date: Sun, 29 Oct 2017 04:58:20 +0530 Subject: [PATCH 176/234] Hacktoberfest Hacktoberfest Sign In Sheet 2017! The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! Instruction In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. Git and Pull Request Resources Github The Net Ninja Awesome-Git How to Create a Pull Request Click on the fork on the top to fork this repo. Go to your repo where you forked the project. Hit the clone button on your forked repo and copy the given link. On your terminal / command prompt, type "git clone [put the link here]". Change the index file in the folder. Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" Push the commit. For example, type "git push [remote-name] master". Go back to the original repo. Hit "new pull request" and compare between forks. Confirm the pull request and that's it! --- Hacktoberfest | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Hacktoberfest diff --git a/Hacktoberfest b/Hacktoberfest new file mode 100644 index 000000000..316700cd9 --- /dev/null +++ b/Hacktoberfest @@ -0,0 +1,26 @@ +Hacktoberfest Sign In Sheet 2017! + +The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! + +Instruction + +In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. + +Git and Pull Request Resources + +Github +The Net Ninja +Awesome-Git +How to Create a Pull Request + +Click on the fork on the top to fork this repo. +Go to your repo where you forked the project. +Hit the clone button on your forked repo and copy the given link. +On your terminal / command prompt, type "git clone [put the link here]". +Change the index file in the folder. +Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. +Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" +Push the commit. For example, type "git push [remote-name] master". +Go back to the original repo. +Hit "new pull request" and compare between forks. +Confirm the pull request and that's it! From 4813199b4d43bffe9720422e7cf4797fcc2eaa10 Mon Sep 17 00:00:00 2001 From: Bug Date: Mon, 30 Oct 2017 00:12:22 -0200 Subject: [PATCH 177/234] Another minor spelling fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e2117dfd..65e96c1c0 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ The maintainers have to: To become part of the core team one has to be invited. Invitations happen only if all the core team agrees. -If a member of the core team is not active for at least to months, they will probably be removed from the core team. +If a member of the core team is not active for at least two months, they will probably be removed from the core team. ## Contact From 7becb60f65033d4eea1e09ee083ca9ff6ad893d8 Mon Sep 17 00:00:00 2001 From: kiss-me1997 <33254635+kiss-me1997@users.noreply.github.com> Date: Tue, 31 Oct 2017 18:09:03 +0530 Subject: [PATCH 178/234] Readme Hacktoberfest Sign In Sheet 2017! The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! Instruction In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. Git and Pull Request Resources Github The Net Ninja Awesome-Git How to Create a Pull Request Click on the fork on the top to fork this repo. Go to your repo where you forked the project. Hit the clone button on your forked repo and copy the given link. On your terminal / command prompt, type "git clone [put the link here]". Change the index file in the folder. Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" Push the commit. For example, type "git push [remote-name] master". Go back to the original repo. Hit "new pull request" and compare between forks. Confirm the pull request and that's it! Installation Make sure git is installed. --- Readme | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Readme diff --git a/Readme b/Readme new file mode 100644 index 000000000..a8f1c6b0d --- /dev/null +++ b/Readme @@ -0,0 +1,29 @@ +Hacktoberfest Sign In Sheet 2017! + +The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! + +Instruction + +In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. + +Git and Pull Request Resources + +Github +The Net Ninja +Awesome-Git +How to Create a Pull Request + +Click on the fork on the top to fork this repo. +Go to your repo where you forked the project. +Hit the clone button on your forked repo and copy the given link. +On your terminal / command prompt, type "git clone [put the link here]". +Change the index file in the folder. +Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. +Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" +Push the commit. For example, type "git push [remote-name] master". +Go back to the original repo. +Hit "new pull request" and compare between forks. +Confirm the pull request and that's it! +Installation + +Make sure git is installed. From 85c8558b38988f33442a05a82c8ea37c17445ecd Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 11 Nov 2017 14:23:06 +0000 Subject: [PATCH 179/234] Add a newbie section to the installation. Added a TL;DR for the people who don't like big walls of text. Explains it very simply for newbies like myself to help them choose what they need. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 65e96c1c0..c12e0b877 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ msbuild Then add a reference to CodeCracker.dll from within the Analyzers node inside References, in Visual Studio. +TL;DR: +If you want to use CodeCracker in all your projects, install the Visual Studio extension ([C#](https://visualstudiogallery.msdn.microsoft.com/ab588981-91a5-478c-8e65-74d0ff450862), [VB](https://visualstudiogallery.msdn.microsoft.com/1a5f9551-e831-4812-abd0-ac48603fc2c1)). If you want to use CodeCracker for just one project, install the Nuget package as described above. + ## SonarQube Plugin CodeCracker has a SonarQube Plugin that can downloaded at [Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). From 414cae960360a176edaf2633059e6ceb62641a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=A9ury=20Sim=C3=B5es=20Bazzo?= Date: Fri, 17 Nov 2017 17:30:13 -0200 Subject: [PATCH 180/234] first commit --- .../Style/TaskNameAsyncAnalyzer.cs | 13 +++++++- .../Style/TaskNameASyncTests.cs | 33 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs index 6c0f8997c..8731f531c 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs @@ -7,6 +7,10 @@ namespace CodeCracker.CSharp.Style { + + + + [DiagnosticAnalyzer(LanguageNames.CSharp)] public class TaskNameAsyncAnalyzer : DiagnosticAnalyzer { @@ -32,7 +36,14 @@ public class TaskNameAsyncAnalyzer : DiagnosticAnalyzer private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; + var method = (MethodDeclarationSyntax)context.Node; + + //for teste + var semanticModel = context.SemanticModel; + if (method.IsImplementingInterface(semanticModel)) return; + + if (method.Identifier.ToString().EndsWith("Async")) return; if (method.Modifiers.Any(SyntaxKind.NewKeyword, SyntaxKind.OverrideKeyword)) return; @@ -44,7 +55,7 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) context.ReportDiagnostic(diag); return; } - var semanticModel = context.SemanticModel; + semanticModel = context.SemanticModel; var returnType = semanticModel.GetSymbolInfo(method.ReturnType).Symbol as INamedTypeSymbol; if (returnType == null) return; diff --git a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs index 76107647d..b8a56c098 100644 --- a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs @@ -7,6 +7,39 @@ namespace CodeCracker.Test.CSharp.Style { public class TaskNameAsyncTests : CodeFixVerifier { + + [Fact] + public async Task TaskNameAsyncMethodEqualsInterface() + { + const string source = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public interface IBar + { + Task Foo(); + } + + public class Bar : IBar + { + public Task Foo() + { } + } + }"; + + var expected = new DiagnosticResult + { + Id = DiagnosticId.TaskNameAsync.ToDiagnosticId(), + Message = string.Format(TaskNameAsyncAnalyzer.MessageFormat, "FooAsync"), + Severity = DiagnosticSeverity.Info, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 26) } + }; + + await VerifyCSharpDiagnosticAsync(source, expected); + } + + [Fact] public async Task TaskNameAsyncMethodCorrect() { From f7635048f02006f379943e6124418ea7ed14e776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=A9ury=20Sim=C3=B5es=20Bazzo?= Date: Sun, 19 Nov 2017 22:40:34 -0200 Subject: [PATCH 181/234] Last Commit --- .../CodeCracker/Style/TaskNameAsyncAnalyzer.cs | 13 ------------- .../CodeCracker.Test/Style/TaskNameASyncTests.cs | 6 ++---- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs index 8731f531c..daaf8019f 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs @@ -7,10 +7,6 @@ namespace CodeCracker.CSharp.Style { - - - - [DiagnosticAnalyzer(LanguageNames.CSharp)] public class TaskNameAsyncAnalyzer : DiagnosticAnalyzer { @@ -38,31 +34,22 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) if (context.IsGenerated()) return; var method = (MethodDeclarationSyntax)context.Node; - - //for teste var semanticModel = context.SemanticModel; if (method.IsImplementingInterface(semanticModel)) return; - - if (method.Identifier.ToString().EndsWith("Async")) return; if (method.Modifiers.Any(SyntaxKind.NewKeyword, SyntaxKind.OverrideKeyword)) return; - var errorMessage = method.Identifier.ToString() + "Async"; var diag = Diagnostic.Create(Rule, method.Identifier.GetLocation(), errorMessage); - if (method.Modifiers.Any(SyntaxKind.AsyncKeyword)) { context.ReportDiagnostic(diag); return; } - semanticModel = context.SemanticModel; var returnType = semanticModel.GetSymbolInfo(method.ReturnType).Symbol as INamedTypeSymbol; if (returnType == null) return; - if (returnType.ToString() != "System.Threading.Tasks.Task" && (!returnType.IsGenericType || returnType.ConstructedFrom.ToString() != "System.Threading.Tasks.Task")) return; - if (method.IsImplementingInterface(semanticModel)) return; context.ReportDiagnostic(diag); } } diff --git a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs index b8a56c098..80d73afea 100644 --- a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs @@ -7,9 +7,8 @@ namespace CodeCracker.Test.CSharp.Style { public class TaskNameAsyncTests : CodeFixVerifier { - [Fact] - public async Task TaskNameAsyncMethodEqualsInterface() + public async Task TaskNameAsyncMethodEqualsNameMethodInterface() { const string source = @" using System.Threading.Tasks; @@ -38,8 +37,7 @@ public Task Foo() await VerifyCSharpDiagnosticAsync(source, expected); } - - + [Fact] public async Task TaskNameAsyncMethodCorrect() { From e2a96e26edae3dab77338c003ed115e973feb1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=A9ury=20Sim=C3=B5es=20Bazzo?= Date: Mon, 20 Nov 2017 11:18:36 -0200 Subject: [PATCH 182/234] Fix Bug: CC0061: Implementing interface using async keyword should not raise a diagnostic #936 --- src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs | 1 - test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs index daaf8019f..160d792e2 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncAnalyzer.cs @@ -32,7 +32,6 @@ public class TaskNameAsyncAnalyzer : DiagnosticAnalyzer private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; - var method = (MethodDeclarationSyntax)context.Node; var semanticModel = context.SemanticModel; if (method.IsImplementingInterface(semanticModel)) return; diff --git a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs index 80d73afea..e897d37b1 100644 --- a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs @@ -26,7 +26,6 @@ public Task Foo() { } } }"; - var expected = new DiagnosticResult { Id = DiagnosticId.TaskNameAsync.ToDiagnosticId(), @@ -37,7 +36,7 @@ public Task Foo() await VerifyCSharpDiagnosticAsync(source, expected); } - + [Fact] public async Task TaskNameAsyncMethodCorrect() { From 3162618c943a3f7522761bac86bb624556e3e763 Mon Sep 17 00:00:00 2001 From: Pascal Berger Date: Thu, 14 Dec 2017 20:44:45 +0100 Subject: [PATCH 183/234] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c12e0b877..a8cb57814 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ If you want to use CodeCracker in all your projects, install the Visual Studio e ## SonarQube Plugin -CodeCracker has a SonarQube Plugin that can downloaded at [Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). +CodeCracker has a SonarQube Plugin that can be downloaded at [Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). ## Contributing From b890c9aa19340f8bae05d7d7ed176d2c052db06a Mon Sep 17 00:00:00 2001 From: Matt Rouse Date: Mon, 18 Dec 2017 16:26:51 +0000 Subject: [PATCH 184/234] Fix issue/958 Don't suggest changes for Async Main --- .../Style/TaskNameAsyncCodeFixProvider.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs index ac8192347..198444fb5 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs @@ -22,10 +22,25 @@ public class TaskNameAsyncCodeFixProvider : CodeFixProvider public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); + + if (GetMethodName(diagnostic) == "Main" && IsUsingCSharp7(diagnostic)) + return Task.FromResult(0); + context.RegisterCodeFix(CodeAction.Create("Change method name including 'Async'.", c => ChangeMethodNameAsync(context.Document, diagnostic, c), nameof(TaskNameAsyncCodeFixProvider)), diagnostic); + return Task.FromResult(0); } + private static string GetMethodName(Diagnostic diagnostic) + { + return diagnostic.Location.SourceTree.ToString().Substring(diagnostic.Location.SourceSpan.Start, diagnostic.Location.SourceSpan.End - diagnostic.Location.SourceSpan.Start); + } + + private static bool IsUsingCSharp7(Diagnostic diagnostic) + { + return ((CSharpParseOptions)diagnostic.Location.SourceTree.Options).LanguageVersion.ToString() == "CSharp7"; + } + private static async Task ChangeMethodNameAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); From 5ffe60b48e091b424a6ccd0949c64a5b576afadc Mon Sep 17 00:00:00 2001 From: BugAgain Date: Tue, 30 Jan 2018 17:47:14 -0200 Subject: [PATCH 185/234] Not the cat We are not referring to the :cat: here --- .../Refactoring/AllowMembersOrderingAnalyzerTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs index 07c58f2cc..724a2cfd6 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs @@ -14,7 +14,7 @@ protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() [Theory] [InlineData("class")] [InlineData("struct")] - public async void AllowMembersOrderingForEmptyTypeShouldNotTiggerDiagnostic(string typeDeclaration) + public async void AllowMembersOrderingForEmptyTypeShouldNotTriggerDiagnostic(string typeDeclaration) { var test = @" " + typeDeclaration + @" Foo @@ -27,7 +27,7 @@ public async void AllowMembersOrderingForEmptyTypeShouldNotTiggerDiagnostic(stri [Theory] [InlineData("class")] [InlineData("struct")] - public async void AllowMembersOrderingForOneMemberShouldNotTiggerDiagnostic(string typeDeclaration) + public async void AllowMembersOrderingForOneMemberShouldNotTriggerDiagnostic(string typeDeclaration) { var test = @" " + typeDeclaration + @" Foo @@ -41,7 +41,7 @@ public async void AllowMembersOrderingForOneMemberShouldNotTiggerDiagnostic(stri [Theory] [InlineData("class")] [InlineData("struct")] - public async void AllowMembersOrderingForMoreThanOneMemberShouldTiggerDiagnostic(string typeDeclaration) + public async void AllowMembersOrderingForMoreThanOneMemberShouldTriggerDiagnostic(string typeDeclaration) { var test = @" " + typeDeclaration + @" Foo From 01d956f39f0e91802b30fb30dfc56d9938ab7162 Mon Sep 17 00:00:00 2001 From: codetriage-readme-bot Date: Mon, 26 Feb 2018 14:11:58 -0600 Subject: [PATCH 186/234] Add CodeTriage badge to code-cracker/code-cracker Adds a badge showing the number of people helping this repo on CodeTriage. [![Open Source Helpers](https://www.codetriage.com/code-cracker/code-cracker/badges/users.svg)](https://www.codetriage.com/code-cracker/code-cracker) ## What is CodeTriage? CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed [Read more about the CodeTriage project](https://www.codetriage.com/what). ## Why am I getting this PR? Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly about 1 year ago, [andrecarlucci](https://github.com/andrecarlucci) added this project to CodeTriage in order to start contributing. Since then, 6 people have subscribed to help this repo. ## What does adding a badge accomplish? Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project. You can see an example of a CodeTriage badge on these popular OSS READMEs: - [![Email clients like GMAIL do not render SVG images](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails - [![Email clients like GMAIL do not render SVG images](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal ## Have a question or comment? While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics. If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again. Thanks for making your project Open Source! Any feedback is greatly appreciated. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a8cb57814..3f104f6f0 100644 --- a/README.md +++ b/README.md @@ -64,9 +64,9 @@ If you want to use CodeCracker in all your projects, install the Visual Studio e ## SonarQube Plugin -CodeCracker has a SonarQube Plugin that can be downloaded at [Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). +CodeCracker has a SonarQube Plugin that can be downloaded at [Plugins HomePage](http://docs.sonarqube.org/display/PLUG/Other+Plugins). -## Contributing +## Contributing [![Open Source Helpers](https://www.codetriage.com/code-cracker/code-cracker/badges/users.svg)](https://www.codetriage.com/code-cracker/code-cracker) The main supported IDE for development is Visual Studio 2015. If you want to use VS 2015 to contribute to Code Cracker use @@ -90,7 +90,7 @@ be assigned to this team. The easiest way to start is looking into the issues that are [up for grabs](https://github.com/code-cracker/code-cracker/labels/up-for-grabs). You -may ask to work on any of them, read below to see how. +may ask to work on any of them, read below to see how. You can also triage issues which may include reproducing bug reports, or asking for vital information such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to code-cracker on CodeTriage](https://www.codetriage.com/code-cracker/code-cracker). If you are just starting with Roslyn, want to contribute, and feel you are not yet ready to start working on full analyzers or code fixes, you can start helping with areas that are From fe14d752024d5d894bba6e9493a1c9bf4f2e3656 Mon Sep 17 00:00:00 2001 From: Justin Clareburt Date: Wed, 28 Feb 2018 09:40:58 -0800 Subject: [PATCH 187/234] Added release notes to VSIX manifest (C# and VB). Release notes point to ChangeLog. --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 1 + src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest | 1 + 2 files changed, 2 insertions(+) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index 7af8869e2..aa1218012 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -9,6 +9,7 @@ Build status Nuget count Nuget downloads Issues open This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. http://code-cracker.github.io/ LICENSE.txt + http://code-cracker.github.io/changelog.html codecrackerlogo.png ccexample.png ReSharper, Refactoring, code analysis, analyzer, CodeRush, roslyn, roslyn c#, Refactoring c# Roslyn diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index 6423f798e..3de517a30 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -9,6 +9,7 @@ Build status Nuget count Nuget downloads Issues open This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. http://code-cracker.github.io/ LICENSE.txt + http://code-cracker.github.io/changelog.html codecrackerlogo.png ccexample.png ReSharper, Refactoring, code analysis, analyzer, CodeRush, roslyn, roslyn c#, Refactoring c# Roslyn From e680450e1f2c93f6dac5b1171933f173aa776705 Mon Sep 17 00:00:00 2001 From: Justin Clareburt Date: Wed, 28 Feb 2018 10:16:37 -0800 Subject: [PATCH 188/234] Started adding features to ReadeMe file. Added Design features. --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 3f104f6f0..bb5318b6a 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,20 @@ our task board, definition of done, definition of ready, etc. This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. +## Features + +The list of features is documented here: http://code-cracker.github.io/diagnostics.html + +#### Design +Code | Analyzer | Severity | Description +-- | -- | -- | -- +[CC0003](http://code-cracker.github.io/diagnostics/CC0003.html) | CatchEmptyAnalyzer | Warning | Catch statements with no Exception as an argument is not recommended. Consider adding an Exception class to the catch statement. +[CC0004](http://code-cracker.github.io/diagnostics/CC0004.html) | EmptyCatchBlockAnalyzer | Warning | An empty catch block suppress all errors and shouldn’t be used. If the error is expected consider logging it or changing the control flow such that it is explicit. +[CC0016](http://code-cracker.github.io/diagnostics/CC0016.html) | CopyEventToVariableBeforeFireAnalyzer | Warning | Events should always be checked for null before being invoked. As in a multi-threading context it is possible for an event to be unsuscribed between the moment where it is checked to be non-null and the moment it is raised, the event must be copied to a temporary variable before the check. +[CC0021](http://code-cracker.github.io/diagnostics/CC0021.html) | NameOfAnalyzer | Warning | In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produce code that is easier to refactor. +[CC0024](http://code-cracker.github.io/diagnostics/CC0024.html) | StaticConstructorExceptionAnalyzer | Warning | Static constructor are called before the first time a class is used but the caller doesn’t control when exactly. Exception thrown in this context force callers to use ‘try’ block around any useage of the class and should be avoided. +[CC0031](http://code-cracker.github.io/diagnostics/CC0031.html) | UseInvokeMethodToFireEventAnalyzer | Warning | In C#6 a delegate can be invoked using the null-propagating operator (?.) and it’s invoke method to avoid throwing a NullReference exception when there is no method attached to the delegate. + ## Installing You may use CodeCracker in two ways: as an analyzer library that you install with Nuget into your project or as a Visual Studio extension. From c5ffd288bbfcf70d85dd0bcafff084d3d9ae37c7 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 6 May 2018 21:33:24 -0300 Subject: [PATCH 189/234] Remove hacktober fest old files --- Create Readme | 26 -------------------------- Readme | 29 ----------------------------- 2 files changed, 55 deletions(-) delete mode 100644 Create Readme delete mode 100644 Readme diff --git a/Create Readme b/Create Readme deleted file mode 100644 index 316700cd9..000000000 --- a/Create Readme +++ /dev/null @@ -1,26 +0,0 @@ -Hacktoberfest Sign In Sheet 2017! - -The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! - -Instruction - -In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. - -Git and Pull Request Resources - -Github -The Net Ninja -Awesome-Git -How to Create a Pull Request - -Click on the fork on the top to fork this repo. -Go to your repo where you forked the project. -Hit the clone button on your forked repo and copy the given link. -On your terminal / command prompt, type "git clone [put the link here]". -Change the index file in the folder. -Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. -Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" -Push the commit. For example, type "git push [remote-name] master". -Go back to the original repo. -Hit "new pull request" and compare between forks. -Confirm the pull request and that's it! diff --git a/Readme b/Readme deleted file mode 100644 index a8f1c6b0d..000000000 --- a/Readme +++ /dev/null @@ -1,29 +0,0 @@ -Hacktoberfest Sign In Sheet 2017! - -The goal of this repo is to help beginners who are doing their first pull requests. Feel free to join! - -Instruction - -In the index file, look for the 'ol' tag. Then insert a 'li' tag with your link to your profile. - -Git and Pull Request Resources - -Github -The Net Ninja -Awesome-Git -How to Create a Pull Request - -Click on the fork on the top to fork this repo. -Go to your repo where you forked the project. -Hit the clone button on your forked repo and copy the given link. -On your terminal / command prompt, type "git clone [put the link here]". -Change the index file in the folder. -Afterward, on your terminal / command prompt, type "git add index.html"; then 'git commit -m "[type a message]" '. -Create a remote to link the repository on github to your local workspace. use "git remote add [remote-name] [put the github link here]" -Push the commit. For example, type "git push [remote-name] master". -Go back to the original repo. -Hit "new pull request" and compare between forks. -Confirm the pull request and that's it! -Installation - -Make sure git is installed. From 06ae9c914e692ae86c1871070b1e89184caba4ee Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 19 May 2018 23:26:59 -0300 Subject: [PATCH 190/234] Fix tabs and spaces on default.ps1 --- default.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/default.ps1 b/default.ps1 index aef7b7d5d..cf299c631 100644 --- a/default.ps1 +++ b/default.ps1 @@ -84,7 +84,7 @@ Task ILMerge-VB { ILMerge $releaseDirVB $dllVB $projectFileVB $projectDirVB } Task ILMerge-CS { ILMerge $releaseDirCS $dllCS $projectFileCS $projectDirCS } function ILMerge($releaseDir, $dll, $projectFile, $projectDir) { - Write-Host "IL Merge:" + Write-Host "IL Merge:" $mergedDir = $tempDir if (!(Test-Path $mergedDir)) { mkdir "$mergedDir" } $inputDll = "$releaseDir\$dll" @@ -112,11 +112,11 @@ function ILMerge($releaseDir, $dll, $projectFile, $projectDir) { $releaseMergedDir = "$releaseDir\merged" if (!(Test-Path $releaseMergedDir)) { mkdir $releaseMergedDir | Out-Null } cp $mergedDll "$releaseMergedDir\" -Force - Write-Host " $dll -> $releaseMergedDir\$dll" + Write-Host " $dll -> $releaseMergedDir\$dll" $mergedPdb = Change-Extension $mergedDll "pdb" cp $mergedPdb "$releaseMergedDir\" -Force - $pdb = (ls $mergedPdb).Name - Write-Host " $pdb -> $releaseMergedDir\$pdb" + $pdb = (ls $mergedPdb).Name + Write-Host " $pdb -> $releaseMergedDir\$pdb" } function Change-Extension ($filename, $extension) { @@ -189,7 +189,7 @@ function PackNuget($language, $dir, $nuspecFile, $nupkgFile) { $nupkgFile = $nupkgFile -f $xml.package.metadata.version . $nugetExe pack "$nuspecFile" -OutputDirectory "$dir" $nuspecFileName = (ls $nuspecFile).Name - Write-Host " $nuspecFileName ($language/$($xml.package.metadata.version)) -> $nupkgFile" + Write-Host " $nuspecFileName ($language/$($xml.package.metadata.version)) -> $nupkgFile" if ($isAppVeyor) { Write-Host "Pushing nuget artifact for $language..." appveyor PushArtifact $nupkgFile From 3cf1b2fbd8f680455e3a2b5885e5689afd3216ef Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 19 May 2018 23:39:05 -0300 Subject: [PATCH 191/234] Add .debug vsix projects to facilitate debug As we are il merging for release the vsix did not contain the common dll and failed on debug when running the vs instance. This fix it. --- CodeCracker.CSharp.sln | 11 +++ CodeCracker.VisualBasic.sln | 13 +++ CodeCracker.sln | 25 +++++ .../CodeCracker.Vsix.Debug.csproj | 93 +++++++++++++++++++ .../source.extension.debug.vsixmanifest | 34 +++++++ .../CodeCracker.Vsix.Debug.csproj | 93 +++++++++++++++++++ .../source.extension.debug.vsixmanifest | 34 +++++++ 7 files changed, 303 insertions(+) create mode 100644 src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj create mode 100644 src/CSharp/CodeCracker.Vsix/source.extension.debug.vsixmanifest create mode 100644 src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj create mode 100644 src/VisualBasic/CodeCracker.Vsix/source.extension.debug.vsixmanifest diff --git a/CodeCracker.CSharp.sln b/CodeCracker.CSharp.sln index e075a10f0..79a90944e 100644 --- a/CodeCracker.CSharp.sln +++ b/CodeCracker.CSharp.sln @@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{E3B0C133-B97E-46B9-809D-16BB762EF74F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -89,6 +91,12 @@ Global {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.Build.0 = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -97,4 +105,7 @@ Global {051F1BE2-9A44-4B84-9DF8-6537852B7BBC} = {7B4F0131-D598-4692-9E2C-111E6C42C6AD} {40545653-8444-49E0-8DAD-BBB381F8A3B2} = {7B4F0131-D598-4692-9E2C-111E6C42C6AD} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {80743E34-82D0-4E0A-9514-0C85FF873E14} + EndGlobalSection EndGlobal diff --git a/CodeCracker.VisualBasic.sln b/CodeCracker.VisualBasic.sln index b338754d2..d9cc68f85 100644 --- a/CodeCracker.VisualBasic.sln +++ b/CodeCracker.VisualBasic.sln @@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.csproj", "{B7B513B4-0317-4F32-B560-4BFC4FAEC239}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,6 +87,14 @@ Global {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.Build.0 = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -93,4 +103,7 @@ Global {D1591C8E-982D-402F-B3CB-1D1662104425} = {3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6} {22D6C608-E7F1-4236-BB07-BE5F97A4C810} = {3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0D75A128-4A6D-4847-9699-93EF828F5B40} + EndGlobalSection EndGlobal diff --git a/CodeCracker.sln b/CodeCracker.sln index 64406cda0..223e057b8 100644 --- a/CodeCracker.sln +++ b/CodeCracker.sln @@ -55,6 +55,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6 test.ps1 = test.ps1 EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{E3B0C133-B97E-46B9-809D-16BB762EF74F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -123,6 +127,22 @@ Global {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.Build.0 = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.Build.0 = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU + {E3B0C133-B97E-46B9-809D-16BB762EF74F}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -136,5 +156,10 @@ Global {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} {234973E7-794D-4BC5-8D5F-FB98D8BFA967} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} {C5584F20-6E93-4D2D-B6F0-141B977AFC9F} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} + {E3B0C133-B97E-46B9-809D-16BB762EF74F} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EF50C6AB-1421-41AE-8CB3-927AB24A69EA} EndGlobalSection EndGlobal diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj new file mode 100644 index 000000000..b80feb9e7 --- /dev/null +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj @@ -0,0 +1,93 @@ + + + + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + 15.0 + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {E3B0C133-B97E-46B9-809D-16BB762EF74F} + Library + Properties + CodeCracker + CodeCracker.CSharp + v4.5.2 + false + false + false + false + false + false + Roslyn + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Program + $(DevEnvDir)devenv.exe + /rootsuffix Roslyn + + + + Designer + + + + + {753d4757-fcba-43ba-b1be-89201acda192} + CodeCracker.Common + + + {FF1097FB-A890-461B-979E-064697891B96} + CodeCracker + + + + + Always + true + + + Always + true + + + Always + true + + + + + + \ No newline at end of file diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.debug.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.debug.vsixmanifest new file mode 100644 index 000000000..e81a560f6 --- /dev/null +++ b/src/CSharp/CodeCracker.Vsix/source.extension.debug.vsixmanifest @@ -0,0 +1,34 @@ + + + + + Code Cracker for C# + An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. +Check the official project site on code-cracker.github.io. +Build status Nuget count Nuget downloads Issues open +This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. + http://code-cracker.github.io/ + LICENSE.txt + http://code-cracker.github.io/changelog.html + codecrackerlogo.png + ccexample.png + ReSharper, Refactoring, code analysis, analyzer, CodeRush, roslyn, roslyn c#, Refactoring c# Roslyn + + + + + + + + + + + + + + + + + + + diff --git a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj new file mode 100644 index 000000000..bee9c5a1c --- /dev/null +++ b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj @@ -0,0 +1,93 @@ + + + + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + 14.0 + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38} + Library + Properties + CodeCracker + CodeCracker.VisualBasic + v4.5.2 + false + false + false + false + false + false + Roslyn + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Program + $(DevEnvDir)devenv.exe + /rootsuffix Roslyn + + + + Designer + + + + + Always + true + + + Always + true + + + Always + true + + + + + {753d4757-fcba-43ba-b1be-89201acda192} + CodeCracker.Common + + + {41fa4971-d354-4647-a269-4a886da2ef4c} + CodeCracker + + + + + + \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.debug.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.debug.vsixmanifest new file mode 100644 index 000000000..6f6ab34bd --- /dev/null +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.debug.vsixmanifest @@ -0,0 +1,34 @@ + + + + + Code Cracker for Visual Basic + An analyzer library for VB that uses Roslyn to produce refactorings, code analysis, and other niceties. +Check the official project site on code-cracker.github.io. +Build status Nuget count Nuget downloads Issues open +This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. + http://code-cracker.github.io/ + LICENSE.txt + http://code-cracker.github.io/changelog.html + codecrackerlogo.png + ccexample.png + ReSharper, Refactoring, code analysis, analyzer, CodeRush, roslyn, roslyn c#, Refactoring c# Roslyn + + + + + + + + + + + + + + + + + + + From 1fb3fe15ed47d6d9697866af1416c73c1b71698e Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 19 May 2018 23:42:03 -0300 Subject: [PATCH 192/234] Remove support for VS 2015 --- CodeCracker.2015.sln | 140 ------------------ CodeCracker.CSharp.2015.sln | 100 ------------- CodeCracker.VisualBasic.2015.sln | 96 ------------ README.md | 6 +- default.ps1 | 2 +- .../CodeCracker.Vsix.2015.csproj | 84 ----------- .../CodeCracker.Vsix.2015.csproj | 84 ----------- 7 files changed, 3 insertions(+), 509 deletions(-) delete mode 100644 CodeCracker.2015.sln delete mode 100644 CodeCracker.CSharp.2015.sln delete mode 100644 CodeCracker.VisualBasic.2015.sln delete mode 100644 src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj delete mode 100644 src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj diff --git a/CodeCracker.2015.sln b/CodeCracker.2015.sln deleted file mode 100644 index 61766491e..000000000 --- a/CodeCracker.2015.sln +++ /dev/null @@ -1,140 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker", "src\CSharp\CodeCracker\CodeCracker.csproj", "{FF1097FB-A890-461B-979E-064697891B96}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{6BAC4057-7239-485E-A04B-02E687A83BAA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test", "test\CSharp\CodeCracker.Test\CodeCracker.Test.csproj", "{F7843158-046E-4B22-95D7-CAC7BB01283D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "vb", "vb", "{11473308-7FD9-43CE-84CE-5912EEFDD1DC}" -EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cs", "cs", "{90D62FF0-A374-4C14-B827-1FFA8E384E18}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{B7B513B4-0317-4F32-B560-4BFC4FAEC239}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" -EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker.Test", "test\VisualBasic\CodeCracker.Test\CodeCracker.Test.vbproj", "{5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A26BEB5D-9C92-4F60-9789-563A327605C3}" - ProjectSection(SolutionItems) = preProject - src\CodeCracker.nuspec = src\CodeCracker.nuspec - nuget.config = nuget.config - .nuget\packages.config = .nuget\packages.config - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solution Items", "{E1B8ADBF-3442-4EF3-8C6B-146B576340E9}" - ProjectSection(SolutionItems) = preProject - .gitattributes = .gitattributes - .gitignore = .gitignore - CHANGELOG.md = CHANGELOG.md - README.md = README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{234973E7-794D-4BC5-8D5F-FB98D8BFA967}" - ProjectSection(SolutionItems) = preProject - appveyor.yml = appveyor.yml - build.ps1 = build.ps1 - default.ps1 = default.ps1 - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6E93-4D2D-B6F0-141B977AFC9F}" - ProjectSection(SolutionItems) = preProject - test\CSharp\AnalyzeCecil.ps1 = test\CSharp\AnalyzeCecil.ps1 - test\CSharp\AnalyzeCoreFx.ps1 = test\CSharp\AnalyzeCoreFx.ps1 - test\CSharp\AnalyzeRoslyn.ps1 = test\CSharp\AnalyzeRoslyn.ps1 - runTestsCS.ps1 = runTestsCS.ps1 - runTestsVB.ps1 = runTestsVB.ps1 - test.ps1 = test.ps1 - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - DebugNoVsix|Any CPU = DebugNoVsix|Any CPU - Release|Any CPU = Release|Any CPU - ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.Build.0 = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.Build.0 = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.Build.0 = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {FF1097FB-A890-461B-979E-064697891B96} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} - {6BAC4057-7239-485E-A04B-02E687A83BAA} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} - {F7843158-046E-4B22-95D7-CAC7BB01283D} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} - {41FA4971-D354-4647-A269-4A886DA2EF4C} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} - {B7B513B4-0317-4F32-B560-4BFC4FAEC239} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} - {234973E7-794D-4BC5-8D5F-FB98D8BFA967} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} - {C5584F20-6E93-4D2D-B6F0-141B977AFC9F} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} - EndGlobalSection -EndGlobal diff --git a/CodeCracker.CSharp.2015.sln b/CodeCracker.CSharp.2015.sln deleted file mode 100644 index f1ddbefd2..000000000 --- a/CodeCracker.CSharp.2015.sln +++ /dev/null @@ -1,100 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F5240AD-2B4E-48A4-B9FC-7D19DACEF2CD}" - ProjectSection(SolutionItems) = preProject - nuget.config = nuget.config - .nuget\packages.config = .nuget\packages.config - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker", "src\CSharp\CodeCracker\CodeCracker.csproj", "{FF1097FB-A890-461B-979E-064697891B96}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{6BAC4057-7239-485E-A04B-02E687A83BAA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test", "test\CSharp\CodeCracker.Test\CodeCracker.Test.csproj", "{F7843158-046E-4B22-95D7-CAC7BB01283D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7B4F0131-D598-4692-9E2C-111E6C42C6AD}" - ProjectSection(SolutionItems) = preProject - .gitattributes = .gitattributes - .gitignore = .gitignore - CHANGELOG.md = CHANGELOG.md - README.md = README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{051F1BE2-9A44-4B84-9DF8-6537852B7BBC}" - ProjectSection(SolutionItems) = preProject - test\CSharp\AnalyzeCecil.ps1 = test\CSharp\AnalyzeCecil.ps1 - test\CSharp\AnalyzeCoreFx.ps1 = test\CSharp\AnalyzeCoreFx.ps1 - test\CSharp\AnalyzeRoslyn.ps1 = test\CSharp\AnalyzeRoslyn.ps1 - runTestsCS.ps1 = runTestsCS.ps1 - test.ps1 = test.ps1 - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{40545653-8444-49E0-8DAD-BBB381F8A3B2}" - ProjectSection(SolutionItems) = preProject - appveyor.yml = appveyor.yml - build.ps1 = build.ps1 - default.ps1 = default.ps1 - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - DebugNoVsix|Any CPU = DebugNoVsix|Any CPU - Release|Any CPU = Release|Any CPU - ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.Release|Any CPU.Build.0 = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.Release|Any CPU.Build.0 = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {F7843158-046E-4B22-95D7-CAC7BB01283D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {051F1BE2-9A44-4B84-9DF8-6537852B7BBC} = {7B4F0131-D598-4692-9E2C-111E6C42C6AD} - {40545653-8444-49E0-8DAD-BBB381F8A3B2} = {7B4F0131-D598-4692-9E2C-111E6C42C6AD} - EndGlobalSection -EndGlobal diff --git a/CodeCracker.VisualBasic.2015.sln b/CodeCracker.VisualBasic.2015.sln deleted file mode 100644 index cec5830dd..000000000 --- a/CodeCracker.VisualBasic.2015.sln +++ /dev/null @@ -1,96 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker", "src\VisualBasic\CodeCracker\CodeCracker.vbproj", "{41FA4971-D354-4647-A269-4A886DA2EF4C}" -EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CodeCracker.Test", "test\VisualBasic\CodeCracker.Test\CodeCracker.Test.vbproj", "{5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6}" - ProjectSection(SolutionItems) = preProject - .gitattributes = .gitattributes - .gitignore = .gitignore - README.md = README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{5413BEBC-2F00-4B54-98E9-B1A7618C3C2A}" - ProjectSection(SolutionItems) = preProject - nuget.config = nuget.config - .nuget\packages.config = .nuget\packages.config - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D1591C8E-982D-402F-B3CB-1D1662104425}" - ProjectSection(SolutionItems) = preProject - appveyor.yml = appveyor.yml - build.ps1 = build.ps1 - default.ps1 = default.ps1 - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{22D6C608-E7F1-4236-BB07-BE5F97A4C810}" - ProjectSection(SolutionItems) = preProject - runTestsVB.ps1 = runTestsVB.ps1 - test.ps1 = test.ps1 - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Common", "src\Common\CodeCracker.Common\CodeCracker.Common.csproj", "{753D4757-FCBA-43BA-B1BE-89201ACDA192}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", "test\Common\CodeCracker.Test.Common\CodeCracker.Test.Common.csproj", "{1CD1A3EE-28CE-404B-A59E-AEACF762D938}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.2015", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.2015.csproj", "{B7B513B4-0317-4F32-B560-4BFC4FAEC239}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - DebugNoVsix|Any CPU = DebugNoVsix|Any CPU - Release|Any CPU = Release|Any CPU - ReleaseNoVsix|Any CPU = ReleaseNoVsix|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.Release|Any CPU.Build.0 = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Debug|Any CPU.Build.0 = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.ActiveCfg = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.Release|Any CPU.Build.0 = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {753D4757-FCBA-43BA-B1BE-89201ACDA192}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.Release|Any CPU.Build.0 = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {D1591C8E-982D-402F-B3CB-1D1662104425} = {3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6} - {22D6C608-E7F1-4236-BB07-BE5F97A4C810} = {3DB077DC-387D-4AAD-9ECE-96D3D24FB3A6} - EndGlobalSection -EndGlobal diff --git a/README.md b/README.md index bb5318b6a..3d2511162 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,8 @@ CodeCracker has a SonarQube Plugin that can be downloaded at [Plugins HomePage]( ## Contributing [![Open Source Helpers](https://www.codetriage.com/code-cracker/code-cracker/badges/users.svg)](https://www.codetriage.com/code-cracker/code-cracker) -The main supported IDE for development is Visual Studio 2015. -If you want to use VS 2015 to contribute to Code Cracker use -the *.2015.sln files. We recommend migrating to VS 2017 ASAP, as -we might make VS 2015 obsolete at any time. +The main supported IDE for development is Visual Studio 2017. +We do not support VS 2015 anymore. Questions, comments, bug reports, and pull requests are all welcome. Bug reports that include steps-to-reproduce (including code) are diff --git a/default.ps1 b/default.ps1 index cf299c631..35934cb00 100644 --- a/default.ps1 +++ b/default.ps1 @@ -5,7 +5,7 @@ Properties { $srcDir = "$rootDir\src" $testDir = "$rootDir\test" $isAppVeyor = $env:APPVEYOR -eq $true - $slns = ls "$rootDir\*.sln" | ? { ! $_.Name.Contains('.2015.') } + $slns = ls "$rootDir\*.sln" $packagesDir = "$rootDir\packages" $buildNumber = [Convert]::ToInt32($env:APPVEYOR_BUILD_NUMBER).ToString("0000") $nuspecPathCS = "$rootDir\src\CSharp\CodeCracker\CodeCracker.nuspec" diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj deleted file mode 100644 index 05f70110b..000000000 --- a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj +++ /dev/null @@ -1,84 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - Debug - AnyCPU - 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {6BAC4057-7239-485E-A04B-02E687A83BAA} - Library - Properties - CodeCracker - CodeCracker.CSharp - v4.5.2 - false - false - false - false - false - false - Roslyn - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - Program - $(DevEnvDir)devenv.exe - /rootsuffix Roslyn - - - - Designer - - - - - {FF1097FB-A890-461B-979E-064697891B96} - CodeCracker - - - - - Always - true - - - Always - true - - - Always - true - - - - - - \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj deleted file mode 100644 index dcdad50cf..000000000 --- a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.2015.csproj +++ /dev/null @@ -1,84 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - Debug - AnyCPU - 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {B7B513B4-0317-4F32-B560-4BFC4FAEC239} - Library - Properties - CodeCracker - CodeCracker.VisualBasic - v4.5.2 - false - false - false - false - false - false - Roslyn - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - Program - $(DevEnvDir)devenv.exe - /rootsuffix Roslyn - - - - Designer - - - - - Always - true - - - Always - true - - - Always - true - - - - - {41fa4971-d354-4647-a269-4a886da2ef4c} - CodeCracker - - - - - - \ No newline at end of file From 60f441311c0a0811e768223d0c7bee7f2aa0abb3 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sat, 19 May 2018 23:44:15 -0300 Subject: [PATCH 193/234] Update Copyright to 2018 --- src/CSharp/CodeCracker.Vsix/LICENSE.txt | 2 +- src/CSharp/CodeCracker/Properties/AssemblyInfo.cs | 2 +- src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs | 2 +- src/VisualBasic/CodeCracker.Vsix/LICENSE.txt | 2 +- src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb | 2 +- src/VisualBasic/CodeCracker/Properties/AssemblyInfo.cs | 2 +- test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs | 2 +- test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs | 2 +- test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/LICENSE.txt b/src/CSharp/CodeCracker.Vsix/LICENSE.txt index 9d626bb93..2717e6ad3 100644 --- a/src/CSharp/CodeCracker.Vsix/LICENSE.txt +++ b/src/CSharp/CodeCracker.Vsix/LICENSE.txt @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2014-2015 Giovanni Bassi and Elemar Jr. + Copyright 2014-2018 Giovanni Bassi and Elemar Jr. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs index f63d51c3e..8c689a126 100644 --- a/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/CSharp/CodeCracker/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CodeCracker")] -[assembly: AssemblyCopyright("Copyright © 2014-2015")] +[assembly: AssemblyCopyright("Copyright © 2014-2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs index 6acd8b6ed..ff625b1e5 100644 --- a/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs +++ b/src/Common/CodeCracker.Common/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CodeCracker")] -[assembly: AssemblyCopyright("Copyright © 2014-2015")] +[assembly: AssemblyCopyright("Copyright © 2014-2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/src/VisualBasic/CodeCracker.Vsix/LICENSE.txt b/src/VisualBasic/CodeCracker.Vsix/LICENSE.txt index 9d626bb93..2717e6ad3 100644 --- a/src/VisualBasic/CodeCracker.Vsix/LICENSE.txt +++ b/src/VisualBasic/CodeCracker.Vsix/LICENSE.txt @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2014-2015 Giovanni Bassi and Elemar Jr. + Copyright 2014-2018 Giovanni Bassi and Elemar Jr. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb index 4cf3474fd..89f5f1675 100644 --- a/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb +++ b/src/VisualBasic/CodeCracker/My Project/AssemblyInfo.vb @@ -8,7 +8,7 @@ Imports System.Runtime.InteropServices - + diff --git a/src/VisualBasic/CodeCracker/Properties/AssemblyInfo.cs b/src/VisualBasic/CodeCracker/Properties/AssemblyInfo.cs index 68af67824..47c3f28ae 100644 --- a/src/VisualBasic/CodeCracker/Properties/AssemblyInfo.cs +++ b/src/VisualBasic/CodeCracker/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CodeCracker")] -[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyCopyright("Copyright © 2014-2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs index db28a8bed..355d9badb 100644 --- a/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs +++ b/test/CSharp/CodeCracker.Test/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CodeCracker")] -[assembly: AssemblyCopyright("Copyright © 2014-2015")] +[assembly: AssemblyCopyright("Copyright © 2014-2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs index b095e814c..c0189f778 100644 --- a/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs +++ b/test/Common/CodeCracker.Test.Common/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CodeCracker")] -[assembly: AssemblyCopyright("Copyright © 2014-2015")] +[assembly: AssemblyCopyright("Copyright © 2014-2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb index 471e8e0cc..d3b84acfd 100644 --- a/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb +++ b/test/VisualBasic/CodeCracker.Test/My Project/AssemblyInfo.vb @@ -8,7 +8,7 @@ Imports System.Runtime.InteropServices - + From eeae7e78e290c32bc01c8a1933ca24644d05a357 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 00:47:00 -0300 Subject: [PATCH 194/234] Fix vsix debug build --- CodeCracker.CSharp.sln | 2 -- CodeCracker.VisualBasic.sln | 16 ++++----- CodeCracker.sln | 22 ++++-------- .../CodeCracker.Vsix.Debug.csproj | 11 ++---- .../CodeCracker.Vsix/CodeCracker.Vsix.csproj | 5 --- .../source.extension.vsixmanifest} | 0 .../CodeCracker.Vsix.Debug.csproj | 35 ++++++++----------- .../CodeCracker.Vsix/CodeCracker.Vsix.csproj | 9 ++--- .../source.extension.vsixmanifest} | 0 9 files changed, 33 insertions(+), 67 deletions(-) rename src/CSharp/CodeCracker.Vsix/{source.extension.debug.vsixmanifest => debug/source.extension.vsixmanifest} (100%) rename src/VisualBasic/CodeCracker.Vsix/{source.extension.debug.vsixmanifest => debug/source.extension.vsixmanifest} (100%) diff --git a/CodeCracker.CSharp.sln b/CodeCracker.CSharp.sln index 79a90944e..9090838a1 100644 --- a/CodeCracker.CSharp.sln +++ b/CodeCracker.CSharp.sln @@ -62,7 +62,6 @@ Global {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU @@ -95,7 +94,6 @@ Global {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.Build.0 = Release|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution diff --git a/CodeCracker.VisualBasic.sln b/CodeCracker.VisualBasic.sln index d9cc68f85..e4feebe4e 100644 --- a/CodeCracker.VisualBasic.sln +++ b/CodeCracker.VisualBasic.sln @@ -39,7 +39,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Test.Common", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.csproj", "{B7B513B4-0317-4F32-B560-4BFC4FAEC239}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{7F08D429-91E1-4B47-B3B2-A98754C8DFA7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -82,19 +82,15 @@ Global {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {1CD1A3EE-28CE-404B-A59E-AEACF762D938}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.Build.0 = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CodeCracker.sln b/CodeCracker.sln index 223e057b8..0ca6815d1 100644 --- a/CodeCracker.sln +++ b/CodeCracker.sln @@ -55,7 +55,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6 test.ps1 = test.ps1 EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\VisualBasic\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{7F08D429-91E1-4B47-B3B2-A98754C8DFA7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCracker.Vsix.Debug", "src\CSharp\CodeCracker.Vsix\CodeCracker.Vsix.Debug.csproj", "{E3B0C133-B97E-46B9-809D-16BB762EF74F}" EndProject @@ -84,7 +84,6 @@ Global {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {FF1097FB-A890-461B-979E-064697891B96}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BAC4057-7239-485E-A04B-02E687A83BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU {6BAC4057-7239-485E-A04B-02E687A83BAA}.Release|Any CPU.Build.0 = Release|Any CPU @@ -106,7 +105,6 @@ Global {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {41FA4971-D354-4647-A269-4A886DA2EF4C}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Debug|Any CPU.Build.0 = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7B513B4-0317-4F32-B560-4BFC4FAEC239}.Release|Any CPU.Build.0 = Release|Any CPU @@ -127,22 +125,16 @@ Global {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.Release|Any CPU.Build.0 = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.Release|Any CPU.Build.0 = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.DebugNoVsix|Any CPU.ActiveCfg = Debug|Any CPU - {E3B0C133-B97E-46B9-809D-16BB762EF74F}.DebugNoVsix|Any CPU.Build.0 = Debug|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E3B0C133-B97E-46B9-809D-16BB762EF74F}.Release|Any CPU.Build.0 = Release|Any CPU {E3B0C133-B97E-46B9-809D-16BB762EF74F}.ReleaseNoVsix|Any CPU.ActiveCfg = Release|Any CPU - {E3B0C133-B97E-46B9-809D-16BB762EF74F}.ReleaseNoVsix|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -156,7 +148,7 @@ Global {5399E7A8-F8F1-4F2E-A5D2-9C96F3DD2A2D} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} {234973E7-794D-4BC5-8D5F-FB98D8BFA967} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} {C5584F20-6E93-4D2D-B6F0-141B977AFC9F} = {E1B8ADBF-3442-4EF3-8C6B-146B576340E9} - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7} = {11473308-7FD9-43CE-84CE-5912EEFDD1DC} {E3B0C133-B97E-46B9-809D-16BB762EF74F} = {90D62FF0-A374-4C14-B827-1FFA8E384E18} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj index b80feb9e7..a16c94bc4 100644 --- a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj @@ -4,11 +4,6 @@ 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - 15.0 @@ -34,7 +29,7 @@ true full false - bin\Debug\ + debug\bin\Debug\ DEBUG;TRACE prompt 4 @@ -42,7 +37,7 @@ pdbonly true - bin\Release\ + debug\bin\Release\ TRACE prompt 4 @@ -53,7 +48,7 @@ /rootsuffix Roslyn - + Designer diff --git a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj index 12f744c47..94bd31424 100644 --- a/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj +++ b/src/CSharp/CodeCracker.Vsix/CodeCracker.Vsix.csproj @@ -4,11 +4,6 @@ 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - 15.0 diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.debug.vsixmanifest b/src/CSharp/CodeCracker.Vsix/debug/source.extension.vsixmanifest similarity index 100% rename from src/CSharp/CodeCracker.Vsix/source.extension.debug.vsixmanifest rename to src/CSharp/CodeCracker.Vsix/debug/source.extension.vsixmanifest diff --git a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj index bee9c5a1c..55bfcbb15 100644 --- a/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj +++ b/src/VisualBasic/CodeCracker.Vsix/CodeCracker.Vsix.Debug.csproj @@ -1,14 +1,9 @@  - + 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - 14.0 @@ -16,7 +11,7 @@ AnyCPU 2.0 {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {47FBCA0A-029D-4D7A-89F0-EF5D85E93F38} + {7F08D429-91E1-4B47-B3B2-A98754C8DFA7} Library Properties CodeCracker @@ -34,7 +29,7 @@ true full false - bin\Debug\ + debug\bin\Debug\ DEBUG;TRACE prompt 4 @@ -42,7 +37,7 @@ pdbonly true - bin\Release\ + debug\bin\Release\ TRACE prompt 4 @@ -53,10 +48,20 @@ /rootsuffix Roslyn - + Designer + + + {753d4757-fcba-43ba-b1be-89201acda192} + CodeCracker.Common + + + {41fa4971-d354-4647-a269-4a886da2ef4c} + CodeCracker + + Always @@ -71,16 +76,6 @@ true - - - {753d4757-fcba-43ba-b1be-89201acda192} - CodeCracker.Common - - - {41fa4971-d354-4647-a269-4a886da2ef4c} - CodeCracker - - - \ No newline at end of file + diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.debug.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/debug/source.extension.vsixmanifest similarity index 100% rename from src/VisualBasic/CodeCracker.Vsix/source.extension.debug.vsixmanifest rename to src/VisualBasic/CodeCracker.Vsix/debug/source.extension.vsixmanifest From 5d086f3e7d16a86dcc8d79a765454e78824c6600 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 01:06:12 -0300 Subject: [PATCH 195/234] Remove branch vnext from appveyor config --- appveyor.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ac50d45ed..a94277ef7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -62,13 +62,6 @@ deploy: skip_symbols: true on: branch: master -- provider: NuGet - server: https://www.myget.org/F/codecrackerbuild/api/v2/package - api_key: - secure: 42eslsnaZIIcMVVaeC9Qu5NI9yjzLzHWYUGl0HLhl0YurivQezpMyJOwgSVjiGmj - skip_symbols: true - on: - branch: vnext - provider: NuGet server: https://www.myget.org/F/codecrackerbuild/api/v2/package api_key: From 1adbd86401318177329c4f806982ef70d31fc5e8 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 01:22:57 -0300 Subject: [PATCH 196/234] Update Nuget key for AppVeyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a94277ef7..362ed41d3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,7 +51,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: s1aIT1sGbIeG5Ccgree7K+k/h7LOSzPfJOrsWcCuzgFGrcuexPZUwX/CfYnU9w4v + secure: CosNPh0GfqQtJs2da/qdtykCGRhaJ1keXXxAcEFR0jNGAmveTtj01kPfqIlLPjFv skip_symbols: true on: appveyor_repo_tag: true From 29f6d1e2c8e99d7ac3e624cc5298c2e7de407488 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 02:34:26 -0300 Subject: [PATCH 197/234] Update changelog --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b460cecb..38443cb46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,55 @@ ## [Unreleased](https://github.com/code-cracker/code-cracker/tree/HEAD) -[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.3...HEAD) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.1.0...HEAD) + +**Fixed bugs:** + +- TernaryOperatorWithReturnCodeFixProvider NullReferenceException [\#906](https://github.com/code-cracker/code-cracker/issues/906) + +- Update VS Code Galley page -- broken link for code-cracker.github.io [\#546](https://github.com/code-cracker/code-cracker/issues/546) +- Is there any way to config inspect severity? Some errors are not necessary but noisy [\#543](https://github.com/code-cracker/code-cracker/issues/543) +- Prefer "Count" to "Count\(\)" [\#489](https://github.com/code-cracker/code-cracker/issues/489) + +## [v1.1.0](https://github.com/code-cracker/code-cracker/tree/v1.1.0) (2018-05-20) +[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.3...v1.1.0) + +**Implemented enhancements:** + +- Create a reusable FixAllProvider based on IntroduceFieldFromConstructorCodeFixProviderAll [\#910](https://github.com/code-cracker/code-cracker/issues/910) +- Enable CodeCracker to work with .NET Core [\#871](https://github.com/code-cracker/code-cracker/issues/871) +- CC0068 \(Remove private method\): ShouldSerializeXXX\(\) and ResetXXX\(\) should not trigger the message [\#762](https://github.com/code-cracker/code-cracker/issues/762) +- Create PropertyChangedEventArgs statically [\#42](https://github.com/code-cracker/code-cracker/issues/42) + +- CC0013 Check for applicability as argument [\#522](https://github.com/code-cracker/code-cracker/issues/522) +- Make readonly \(for complex value types\) [\#808](https://github.com/code-cracker/code-cracker/issues/808) +- CC0120: Suggest default for switch statements \(C\#\) [\#780](https://github.com/code-cracker/code-cracker/issues/780) +- Remove Unnecessary ToString in String Concatenation [\#753](https://github.com/code-cracker/code-cracker/issues/753) +- Check consistency of optional parameter default value [\#575](https://github.com/code-cracker/code-cracker/issues/575) +- Make accessibility consistent \(code fix for CS0050 to CS0061\) [\#381](https://github.com/code-cracker/code-cracker/issues/381) +- Prefer "Any" to "Count\(\) \> 0" [\#490](https://github.com/code-cracker/code-cracker/issues/490) +- Extract Class to a New File [\#382](https://github.com/code-cracker/code-cracker/issues/382) +- Seal member if possible [\#372](https://github.com/code-cracker/code-cracker/issues/372) +- Remove virtual modifier if possible [\#371](https://github.com/code-cracker/code-cracker/issues/371) +- Remove async and return task directly [\#151](https://github.com/code-cracker/code-cracker/issues/151) +- Change from as operator to direct cast or the opposite [\#65](https://github.com/code-cracker/code-cracker/issues/65) +- Convert loop to linq expression [\#22](https://github.com/code-cracker/code-cracker/issues/22) + +**Fixed bugs:** + +- CC0061 shouldn't pop for async Main [\#958](https://github.com/code-cracker/code-cracker/issues/958) +- Bug: CC0061: Implementing interface using async keyword should not raise a diagnostic [\#936](https://github.com/code-cracker/code-cracker/issues/936) +- Bug CC0031 UseInvokeMethodToFireEventAnalyzer false positive in constructor [\#926](https://github.com/code-cracker/code-cracker/issues/926) +- BUG: CC0014 Casting to interface or implicit casts for the ternary operator are fixed wrong [\#911](https://github.com/code-cracker/code-cracker/issues/911) +- BUG: CC0022 failed to show fix with null coalesce operator [\#870](https://github.com/code-cracker/code-cracker/issues/870) +- BUG: CC0118 - Unnecessary '.ToString\(\)' call in string concatenation [\#866](https://github.com/code-cracker/code-cracker/issues/866) + +**Closed issues:** + +- Support Hacktoberfest event adding hacktoberfest tag. [\#949](https://github.com/code-cracker/code-cracker/issues/949) +- Using Extension & NuGet package together causes VS2017 to crash [\#944](https://github.com/code-cracker/code-cracker/issues/944) +- False postives and NullReferenceException when using eventhandler in code behind for UWP apps. [\#916](https://github.com/code-cracker/code-cracker/issues/916) +- Replace getter only properties with backing readonly field with getter-only auto-property [\#881](https://github.com/code-cracker/code-cracker/issues/881) ## [v1.0.3](https://github.com/code-cracker/code-cracker/tree/v1.0.3) (2017-03-20) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.2...v1.0.3) @@ -38,6 +86,7 @@ **Implemented enhancements:** +- developmentDependency not added when used with SonarLint [\#829](https://github.com/code-cracker/code-cracker/issues/829) - Auto generated files detection [\#773](https://github.com/code-cracker/code-cracker/issues/773) **Fixed bugs:** @@ -49,7 +98,7 @@ - BUG: GC.SuppressFinalize with arrow methods \(CC0029\) [\#809](https://github.com/code-cracker/code-cracker/issues/809) - Bug: CC0039 False positive when concatenating to loop variable propery/field \(StringBuilderInLoop\) [\#797](https://github.com/code-cracker/code-cracker/issues/797) - Bug: CC0033 appears again after adding 'this' keyword [\#795](https://github.com/code-cracker/code-cracker/issues/795) -- CC0061: Implementing interface using async [\#793](https://github.com/code-cracker/code-cracker/issues/793) +- CC0061: Implementing interface using async pattern [\#793](https://github.com/code-cracker/code-cracker/issues/793) - CC0052 Make field readonly does not take ref out into consideration. [\#788](https://github.com/code-cracker/code-cracker/issues/788) - BUG: CallExtensionMethodAsExtensionAnalyzer threw exception when project language was C\# 5.0 [\#781](https://github.com/code-cracker/code-cracker/issues/781) - Bug: UseInvokeMethodToFireEventAnalyzer \(CC0031\) should not raise a diagnostic when already checked for null with a ternary [\#779](https://github.com/code-cracker/code-cracker/issues/779) @@ -225,6 +274,7 @@ - Update VB Allow Members Ordering to work with Modules [\#440](https://github.com/code-cracker/code-cracker/issues/440) - Provide an equivalence key on all code fix providers [\#417](https://github.com/code-cracker/code-cracker/issues/417) - Unit test methods raises CC0091 - "Make \ method static" [\#404](https://github.com/code-cracker/code-cracker/issues/404) +- Validate color from System.Drawing.ColorTranslator.FromHtml [\#1](https://github.com/code-cracker/code-cracker/issues/1) **Fixed bugs:** From ed8b7ed923fd1f059a6620798153ef7c9d030d0c Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 02:34:44 -0300 Subject: [PATCH 198/234] Add helpers to cound analyzers and update changelog --- default.ps1 | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/default.ps1 b/default.ps1 index 35934cb00..da06d79a4 100644 --- a/default.ps1 +++ b/default.ps1 @@ -181,6 +181,30 @@ Task Pack-Nuget-VB-Force { PackNuget "VB" "$rootDir\src\VisualBasic" $nuspecPathVB $nupkgPathVB } +Task Count-Analyzers { + $count = $(ls $rootDir\src\*.cs -Recurse | ? { $_.Name.contains('Analyzer') } | ? { !((cat $_) -match 'abstract class') }).count + Write-Host "Found $count C# Analyzers" + $count = $(ls $rootDir\src\*.cs -Recurse | ? { $_.Name.contains('CodeFix') } | ? { !((cat $_) -match 'abstract class') }).count + Write-Host "Found $count C# Code Fixes" + $count = $(ls $rootDir\src\*.cs -Recurse | ? { $_.Name.contains('FixAll') } | ? { !((cat $_) -match 'abstract class') }).count + Write-Host "Found $count C# Code Fixes All" + $count = $(ls $rootDir\src\*.vb -Recurse | ? { $_.Name.contains('Analyzer') } | ? { !((cat $_) -match 'mustinherit class') }).count + Write-Host "Found $count VB Analyzers" + $count = $(ls $rootDir\src\*.vb -Recurse | ? { $_.Name.contains('CodeFix') } | ? { !((cat $_) -match 'mustinherit class') }).count + Write-Host "Found $count VB Code Fixes" + $count = $(ls $rootDir\src\*.vb -Recurse | ? { $_.Name.contains('FixAll') } | ? { !((cat $_) -match 'mustinherit class') }).count + Write-Host "Found $count VB Code Fixes All" +} + +Task Update-ChangeLog { + # invoke-psake default.ps1 -tasklist update-changelog -parameters @{"token"=""} + echo $token + return + Exec { + github_changelog_generator code-cracker/code-cracker --no-pull-requests --no-issues-wo-labels --exclude-labels "Can't repro","update readme",decision,docs,duplicate,question,invalid,wontfix,Duplicate,Question,Invalid,Wontfix -t $token + } +} + Task Echo { echo echo } function PackNuget($language, $dir, $nuspecFile, $nupkgFile) { From 5a4d7b9f2b36404b1d89416e45fb0749558e01fe Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 02:39:10 -0300 Subject: [PATCH 199/234] Fix changelog --- CHANGELOG.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38443cb46..d44726355 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,5 @@ # Change Log -## [Unreleased](https://github.com/code-cracker/code-cracker/tree/HEAD) - -[Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.1.0...HEAD) - -**Fixed bugs:** - -- TernaryOperatorWithReturnCodeFixProvider NullReferenceException [\#906](https://github.com/code-cracker/code-cracker/issues/906) - -- Update VS Code Galley page -- broken link for code-cracker.github.io [\#546](https://github.com/code-cracker/code-cracker/issues/546) -- Is there any way to config inspect severity? Some errors are not necessary but noisy [\#543](https://github.com/code-cracker/code-cracker/issues/543) -- Prefer "Count" to "Count\(\)" [\#489](https://github.com/code-cracker/code-cracker/issues/489) - ## [v1.1.0](https://github.com/code-cracker/code-cracker/tree/v1.1.0) (2018-05-20) [Full Changelog](https://github.com/code-cracker/code-cracker/compare/v1.0.3...v1.1.0) @@ -29,6 +17,7 @@ - Check consistency of optional parameter default value [\#575](https://github.com/code-cracker/code-cracker/issues/575) - Make accessibility consistent \(code fix for CS0050 to CS0061\) [\#381](https://github.com/code-cracker/code-cracker/issues/381) - Prefer "Any" to "Count\(\) \> 0" [\#490](https://github.com/code-cracker/code-cracker/issues/490) +- Prefer "Count" to "Count\(\)" [\#489](https://github.com/code-cracker/code-cracker/issues/489) - Extract Class to a New File [\#382](https://github.com/code-cracker/code-cracker/issues/382) - Seal member if possible [\#372](https://github.com/code-cracker/code-cracker/issues/372) - Remove virtual modifier if possible [\#371](https://github.com/code-cracker/code-cracker/issues/371) @@ -42,6 +31,7 @@ - Bug: CC0061: Implementing interface using async keyword should not raise a diagnostic [\#936](https://github.com/code-cracker/code-cracker/issues/936) - Bug CC0031 UseInvokeMethodToFireEventAnalyzer false positive in constructor [\#926](https://github.com/code-cracker/code-cracker/issues/926) - BUG: CC0014 Casting to interface or implicit casts for the ternary operator are fixed wrong [\#911](https://github.com/code-cracker/code-cracker/issues/911) +- TernaryOperatorWithReturnCodeFixProvider NullReferenceException [\#906](https://github.com/code-cracker/code-cracker/issues/906) - BUG: CC0022 failed to show fix with null coalesce operator [\#870](https://github.com/code-cracker/code-cracker/issues/870) - BUG: CC0118 - Unnecessary '.ToString\(\)' call in string concatenation [\#866](https://github.com/code-cracker/code-cracker/issues/866) From 7b3e176a16856ec622bb4f4bbb7e178f04b3f37a Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Sun, 20 May 2018 04:31:34 -0300 Subject: [PATCH 200/234] Update dependencies --- .nuget/packages.config | 4 +- CodeCracker.sln | 2 +- build.ps1 | 4 +- default.ps1 => psakefile.ps1 | 10 ++--- src/CSharp/CodeCracker/CodeCracker.csproj | 5 +-- ...nconsistentAccessibilityCodeFixProvider.cs | 2 + .../CodeCracker/Design/NameOfAnalyzer.cs | 2 + .../Extensions/CSharpAnalyzerExtensions.cs | 9 ++++- .../AddBracesToSwitchSectionsAnalyzer.cs | 2 + ...dEventArgsUnnecessaryAllocationAnalyzer.cs | 2 + .../SplitIntoNestedIfFixAllProvider.cs | 3 +- .../Style/StringFormatFixAllProvider.cs | 3 +- .../SwitchToAutoPropCodeFixAllProvider.cs | 3 +- ...ryToStringInStringConcatenationAnalyzer.cs | 10 ++--- .../Style/UseEmptyStringCodeFixProviderAll.cs | 3 +- .../Style/UseStringEmptyCodeFixProviderAll.cs | 3 +- ...osableVariableNotDisposedFixAllProvider.cs | 3 +- .../RemoveUnreachableCodeFixAllProvider.cs | 3 +- .../UnusedParametersCodeFixAllProvider.cs | 3 +- src/CSharp/CodeCracker/packages.config | 2 +- .../CodeCracker.Common.csproj | 5 +-- .../DocumentCodeFixProviderAll.cs | 3 +- src/Common/CodeCracker.Common/packages.config | 2 +- .../CodeCracker/CodeCracker.vbproj | 5 +-- src/VisualBasic/CodeCracker/packages.config | 2 +- .../CodeCracker.Test/CodeCracker.Test.csproj | 40 ++++++++++--------- .../Refactoring/NumericLiteralTests.cs | 1 + .../ConvertToExpressionBodiedMemberTests.cs | 2 + .../Style/RemoveAsyncFromMethodTests.cs | 4 +- .../Usage/RemoveUnusedVariablesTest.cs | 14 ------- test/CSharp/CodeCracker.Test/packages.config | 20 +++++----- .../CodeCracker.Test.Common.csproj | 38 ++++++++++-------- .../CodeCracker.Test.Common/packages.config | 24 ++++++----- .../CodeCracker.Test/CodeCracker.Test.vbproj | 39 +++++++++--------- .../CodeCracker.Test/packages.config | 20 +++++----- 35 files changed, 164 insertions(+), 133 deletions(-) rename default.ps1 => psakefile.ps1 (97%) diff --git a/.nuget/packages.config b/.nuget/packages.config index 9707f7736..ad3995ace 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/CodeCracker.sln b/CodeCracker.sln index 0ca6815d1..4a19abe95 100644 --- a/CodeCracker.sln +++ b/CodeCracker.sln @@ -42,7 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{234973E7 ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml build.ps1 = build.ps1 - default.ps1 = default.ps1 + psakefile.ps1 = psakefile.ps1 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C5584F20-6E93-4D2D-B6F0-141B977AFC9F}" diff --git a/build.ps1 b/build.ps1 index 27cd8f2d8..a5bf95542 100644 --- a/build.ps1 +++ b/build.ps1 @@ -49,7 +49,7 @@ function Download-Nuget { } function Import-Psake { - $psakeModule = "$PSScriptRoot\packages\psake.4.6.0\tools\psake.psm1" + $psakeModule = "$PSScriptRoot\packages\psake.4.7.0\tools\psake\psake.psm1" if ((Test-Path $psakeModule) -ne $true) { Write-Host "Restoring $PSScriptRoot\.nuget with $script:nugetExe" . "$script:nugetExe" restore $PSScriptRoot\.nuget\packages.config -SolutionDirectory $PSScriptRoot @@ -73,7 +73,7 @@ Get-Nuget Import-Psake Import-ILMerge if ($MyInvocation.UnboundArguments.Count -ne 0) { - Invoke-Expression("Invoke-psake -framework '4.6' $PSScriptRoot\default.ps1 -taskList " + $MyInvocation.UnboundArguments -join " ") + Invoke-Expression("Invoke-psake -framework '4.6' $PSScriptRoot\psakefile.ps1 -taskList " + $MyInvocation.UnboundArguments -join " ") } else { . $PSScriptRoot\build.ps1 Build diff --git a/default.ps1 b/psakefile.ps1 similarity index 97% rename from default.ps1 rename to psakefile.ps1 index da06d79a4..146b33f54 100644 --- a/default.ps1 +++ b/psakefile.ps1 @@ -10,11 +10,11 @@ Properties { $buildNumber = [Convert]::ToInt32($env:APPVEYOR_BUILD_NUMBER).ToString("0000") $nuspecPathCS = "$rootDir\src\CSharp\CodeCracker\CodeCracker.nuspec" $nuspecPathVB = "$rootDir\src\VisualBasic\CodeCracker\CodeCracker.nuspec" - $nugetPackagesExe = "$packagesDir\NuGet.CommandLine.4.1.0\tools\NuGet.exe" + $nugetPackagesExe = "$packagesDir\NuGet.CommandLine.4.6.2\tools\NuGet.exe" $nugetExe = if (Test-Path $nugetPackagesExe) { $nugetPackagesExe } else { 'nuget' } $nupkgPathCS = "$rootDir\src\CSharp\CodeCracker.CSharp.{0}.nupkg" $nupkgPathVB = "$rootDir\src\VisualBasic\CodeCracker.VisualBasic.{0}.nupkg" - $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" + $xunitConsoleExe = "$packagesDir\xunit.runner.console.2.3.1\tools\net452\xunit.console.x86.exe" $openCoverExe = "$packagesDir\OpenCover.4.6.519\tools\OpenCover.Console.exe" $dllCS = "CodeCracker.CSharp.dll" $dllVB = "CodeCracker.VisualBasic.dll" @@ -31,9 +31,9 @@ Properties { $releaseDirCS = "$projectDirCS\bin\Release" $logDir = "$rootDir\log" $outputXml = "$logDir\CodeCoverageResults.xml" - $reportGeneratorExe = "$packagesDir\ReportGenerator.2.5.6\tools\ReportGenerator.exe" + $reportGeneratorExe = "$packagesDir\ReportGenerator.3.1.2\tools\ReportGenerator.exe" $coverageReportDir = "$logDir\codecoverage\" - $coverallsNetExe = "$packagesDir\coveralls.io.1.3.4\tools\coveralls.net.exe" + $coverallsNetExe = "$packagesDir\coveralls.io.1.4.2\tools\coveralls.net.exe" $ilmergeExe = "$packagesDir\ilmerge.2.14.1208\tools\ILMerge.exe" $isRelease = $isAppVeyor -and (($env:APPVEYOR_REPO_BRANCH -eq "release") -or ($env:APPVEYOR_REPO_TAG -eq "true")) $isPullRequest = $env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null @@ -233,7 +233,7 @@ function UpdateNuspec($nuspecPath, $language) { function RestorePkgs($sln) { Write-Host "Restoring $sln..." -ForegroundColor Green Retry { - . $nugetExe restore "$sln" -MSBuildVersion 14 -NonInteractive -ConfigFile "$rootDir\nuget.config" + . $nugetExe restore "$sln" -NonInteractive -ConfigFile "$rootDir\nuget.config" if ($LASTEXITCODE) { throw "Nuget restore for $sln failed." } } } diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index 22c6e50a0..337211dff 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -1,5 +1,5 @@  - + 11.0 @@ -223,8 +223,7 @@ - - + diff --git a/src/CSharp/CodeCracker/Design/InconsistentAccessibility/InconsistentAccessibilityCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/InconsistentAccessibility/InconsistentAccessibilityCodeFixProvider.cs index d8937aca7..f99e9e991 100644 --- a/src/CSharp/CodeCracker/Design/InconsistentAccessibility/InconsistentAccessibilityCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Design/InconsistentAccessibility/InconsistentAccessibilityCodeFixProvider.cs @@ -72,6 +72,8 @@ private static async Task GetInconsistentAccessib case InconsistentAccessibilityInIndexerParameterCompilerErrorNumber: inconsistentAccessibilityProvider = new InconsistentAccessibilityInIndexerParameter(); break; + default: + break; } return await inconsistentAccessibilityProvider.GetInconsistentAccessibilityInfoAsync(document, diagnostic, cancellationToken).ConfigureAwait(false); diff --git a/src/CSharp/CodeCracker/Design/NameOfAnalyzer.cs b/src/CSharp/CodeCracker/Design/NameOfAnalyzer.cs index 9681645cc..1631dc9f9 100644 --- a/src/CSharp/CodeCracker/Design/NameOfAnalyzer.cs +++ b/src/CSharp/CodeCracker/Design/NameOfAnalyzer.cs @@ -114,6 +114,8 @@ private static string GetParameterNameThatMatchStringLiteral(LiteralExpressionSy break; case SyntaxKind.AttributeList: break; + default: + break; } parameterName = GetParameterWithIdentifierEqualToStringLiteral(stringLiteral, parameters)?.Identifier.Text; } diff --git a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs index 0ccb8b5a6..6b79daa2b 100644 --- a/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs +++ b/src/CSharp/CodeCracker/Extensions/CSharpAnalyzerExtensions.cs @@ -317,6 +317,8 @@ private static string GetLastIdentifierValueText(CSharpSyntaxNode node) case SyntaxKind.AliasQualifiedName: result = ((AliasQualifiedNameSyntax)node).Name.Identifier.ValueText; break; + default: + break; } return result; } @@ -336,8 +338,9 @@ public static SyntaxToken GetIdentifier(this BaseMethodDeclarationSyntax method) case SyntaxKind.DestructorDeclaration: result = ((DestructorDeclarationSyntax)method).Identifier; break; + default: + return result; } - return result; } @@ -392,6 +395,8 @@ public static MemberDeclarationSyntax WithModifiers(this MemberDeclarationSyntax case SyntaxKind.EventDeclaration: result = ((EventDeclarationSyntax)declaration).WithModifiers(newModifiers); break; + default: + break; } return result; @@ -428,6 +433,8 @@ public static SyntaxTokenList GetModifiers(this MemberDeclarationSyntax memberDe case SyntaxKind.EventDeclaration: result = ((BasePropertyDeclarationSyntax)memberDeclaration).Modifiers; break; + default: + break; } return result; diff --git a/src/CSharp/CodeCracker/Refactoring/AddBracesToSwitchSectionsAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/AddBracesToSwitchSectionsAnalyzer.cs index 33012a4af..6ef64c506 100644 --- a/src/CSharp/CodeCracker/Refactoring/AddBracesToSwitchSectionsAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/AddBracesToSwitchSectionsAnalyzer.cs @@ -47,6 +47,8 @@ internal static bool HasBraces(SwitchSectionSyntax section) if (section.Statements.First() is BlockSyntax && section.Statements.Last() is BreakStatementSyntax) return true; break; + default: + break; } return false; } diff --git a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs index e9924b9d3..a3f061c3e 100644 --- a/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationAnalyzer.cs @@ -78,6 +78,8 @@ private static bool IsAlreadyStatic(ObjectCreationExpressionSyntax objectCreatio var fieldDeclaration = (FieldDeclarationSyntax)memberForObjectCreationExpr; result = ContainsStaticModifier(fieldDeclaration.Modifiers); break; + default: + break; } return result; } diff --git a/src/CSharp/CodeCracker/Refactoring/SplitIntoNestedIfFixAllProvider.cs b/src/CSharp/CodeCracker/Refactoring/SplitIntoNestedIfFixAllProvider.cs index 568e8af7c..3ca46c2ef 100644 --- a/src/CSharp/CodeCracker/Refactoring/SplitIntoNestedIfFixAllProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/SplitIntoNestedIfFixAllProvider.cs @@ -25,8 +25,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(SplitIntoNestedIfCodeFixProvider.MessageFormat, ct => GetFixedSolutionAsync(fixAllContext))); + default: + return null; } - return null; } private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) diff --git a/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs b/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs index 1c3416c81..055b0e517 100644 --- a/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs +++ b/src/CSharp/CodeCracker/Style/StringFormatFixAllProvider.cs @@ -26,8 +26,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(Resources.StringFormatCodeFixProvider_Title, ct => GetFixedSolutionAsync(fixAllContext))); + default: + return null; } - return null; } private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) diff --git a/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixAllProvider.cs b/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixAllProvider.cs index 5499d07c8..8fa876860 100644 --- a/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixAllProvider.cs +++ b/src/CSharp/CodeCracker/Style/SwitchToAutoPropCodeFixAllProvider.cs @@ -27,8 +27,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(Resources.SwitchToAutoPropCodeFixProvider_Title, async ct => await GetFixedSolutionAsync(fixAllContext, await GetSolutionWithDocsAsync(fixAllContext, fixAllContext.Solution)))); + default: + return null; } - return null; } private async static Task GetSolutionWithDocsAsync(FixAllContext fixAllContext, Solution solution) diff --git a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs index 23fa9dcbe..20bc013e4 100644 --- a/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/UnnecessaryToStringInStringConcatenationAnalyzer.cs @@ -70,7 +70,7 @@ private static IEnumerable FilterInvocationsThatAreR foreach (var node in invocationExpressionsThatHaveToStringCall) { var toStringReceiver = GetTypeInfoOfReceiverOfToStringCall(node, semanticModel, cancellationToken); - //As long as the underlying type can not be resolved by the compiler (e.g. undefined type) + //As long as the underlying type can not be resolved by the compiler (e.g. undefined type) //removal is not save. if (toStringReceiver == null || toStringReceiver.TypeKind==TypeKind.Error) continue; @@ -115,7 +115,7 @@ private static ITypeSymbol GetTypeInfoOfOtherNode(SyntaxNode toStringNode, Binar private static bool CheckAddOperationOverloadsOfTypes(ITypeSymbol toStringReceiver, ITypeSymbol otherType) { - //If the underlying type has a custom AddOperator this operator will take precedence over everything else + //If the underlying type has a custom AddOperator this operator will take precedence over everything else if (HasTypeCustomAddOperator(toStringReceiver)) { return false; @@ -128,7 +128,7 @@ private static bool CheckAddOperationOverloadsOfTypes(ITypeSymbol toStringReceiv } //If the underlying type is one of the build in types (numeric, datetime and so on) and the other side is not a string, - //the result a removal is hard to predict and might be wrong. + //the result a removal is hard to predict and might be wrong. if (HasAdditionOperator(toStringReceiver)) { return false; @@ -177,11 +177,11 @@ private static bool HasAdditionOperator(ITypeSymbol type) case SpecialType.System_UIntPtr: case SpecialType.System_DateTime: return true; + default: + break; } if (type.TypeKind == TypeKind.Enum) - { return true; - } return false; } diff --git a/src/CSharp/CodeCracker/Style/UseEmptyStringCodeFixProviderAll.cs b/src/CSharp/CodeCracker/Style/UseEmptyStringCodeFixProviderAll.cs index a26d828df..0b0915ee3 100644 --- a/src/CSharp/CodeCracker/Style/UseEmptyStringCodeFixProviderAll.cs +++ b/src/CSharp/CodeCracker/Style/UseEmptyStringCodeFixProviderAll.cs @@ -42,8 +42,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(UseEmptyStringCodeFixProvider.MessageFormat, ct => GetFixedSolutionAsync(fixAllContext.WithCancellationToken(ct)))); + default: + return null; } - return null; } private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) diff --git a/src/CSharp/CodeCracker/Style/UseStringEmptyCodeFixProviderAll.cs b/src/CSharp/CodeCracker/Style/UseStringEmptyCodeFixProviderAll.cs index 0498b21d0..6d7e92057 100644 --- a/src/CSharp/CodeCracker/Style/UseStringEmptyCodeFixProviderAll.cs +++ b/src/CSharp/CodeCracker/Style/UseStringEmptyCodeFixProviderAll.cs @@ -42,8 +42,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(UseStringEmptyCodeFixProvider.MessageFormat, ct => GetFixedSolutionAsync(fixAllContext.WithCancellationToken(ct)))); + default: + return null; } - return null; } private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedFixAllProvider.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedFixAllProvider.cs index d49053746..d34c097b0 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedFixAllProvider.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedFixAllProvider.cs @@ -25,8 +25,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(DisposableVariableNotDisposedCodeFixProvider.MessageFormat, ct => GetFixedSolutionAsync(fixAllContext))); + default: + return null; } - return null; } private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) diff --git a/src/CSharp/CodeCracker/Usage/RemoveUnreachableCodeFixAllProvider.cs b/src/CSharp/CodeCracker/Usage/RemoveUnreachableCodeFixAllProvider.cs index 936cb1ef5..499cbd6b7 100644 --- a/src/CSharp/CodeCracker/Usage/RemoveUnreachableCodeFixAllProvider.cs +++ b/src/CSharp/CodeCracker/Usage/RemoveUnreachableCodeFixAllProvider.cs @@ -25,8 +25,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(RemoveUnreachableCodeCodeFixProvider.Message, ct => GetFixedSolutionAsync(fixAllContext))); + default: + return null; } - return null; } private async static Task GetFixedSolutionAsync(FixAllContext fixAllContext) diff --git a/src/CSharp/CodeCracker/Usage/UnusedParametersCodeFixAllProvider.cs b/src/CSharp/CodeCracker/Usage/UnusedParametersCodeFixAllProvider.cs index e41a8fa8b..74650b882 100644 --- a/src/CSharp/CodeCracker/Usage/UnusedParametersCodeFixAllProvider.cs +++ b/src/CSharp/CodeCracker/Usage/UnusedParametersCodeFixAllProvider.cs @@ -27,8 +27,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(message, async ct => await GetFixedSolutionAsync(fixAllContext, await GetSolutionWithDocsAsync(fixAllContext, fixAllContext.Solution)))); + default: + return null; } - return null; } private async static Task GetSolutionWithDocsAsync(FixAllContext fixAllContext, Solution solution) diff --git a/src/CSharp/CodeCracker/packages.config b/src/CSharp/CodeCracker/packages.config index fcde436eb..28a6ce22f 100644 --- a/src/CSharp/CodeCracker/packages.config +++ b/src/CSharp/CodeCracker/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index 34f859b17..f2b05c246 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -1,5 +1,5 @@  - + 11.0 @@ -72,8 +72,7 @@ - - + diff --git a/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs b/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs index 255dfc074..c74833924 100644 --- a/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs +++ b/src/Common/CodeCracker.Common/FixAllProviders/DocumentCodeFixProviderAll.cs @@ -34,8 +34,9 @@ public override Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Solution: return Task.FromResult(CodeAction.Create(CodeFixTitle, ct => GetFixedDocumentsAsync(fixAllContext, fixAllContext.Solution.Projects.SelectMany(p => p.Documents)))); + default: + return null; } - return null; } private async static Task GetFixedDocumentsAsync(FixAllContext fixAllContext, IEnumerable documents) diff --git a/src/Common/CodeCracker.Common/packages.config b/src/Common/CodeCracker.Common/packages.config index 847a13861..324cafb10 100644 --- a/src/Common/CodeCracker.Common/packages.config +++ b/src/Common/CodeCracker.Common/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index 02045debc..31f867607 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -1,5 +1,5 @@  - + 11.0 @@ -162,8 +162,7 @@ - - + diff --git a/src/VisualBasic/CodeCracker/packages.config b/src/VisualBasic/CodeCracker/packages.config index bc11241d0..4ce3c94b7 100644 --- a/src/VisualBasic/CodeCracker/packages.config +++ b/src/VisualBasic/CodeCracker/packages.config @@ -1,6 +1,6 @@  - + diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index dcf1020ca..4d186cfbe 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -1,6 +1,7 @@  - - + + + Debug AnyCPU @@ -40,11 +41,8 @@ false - - ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.dll - - - ..\..\..\packages\FluentAssertions.4.19.2\lib\net45\FluentAssertions.Core.dll + + ..\..\..\packages\FluentAssertions.5.3.0\lib\net45\FluentAssertions.dll ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll @@ -61,8 +59,8 @@ ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll - - ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll @@ -93,6 +91,9 @@ ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll + + ..\..\..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + @@ -101,14 +102,14 @@ ..\..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll - - ..\..\..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll + + ..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - ..\..\..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll + + ..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - ..\..\..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll + + ..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll @@ -227,18 +228,21 @@ - - + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/src/CSharp/CodeCracker/packages.config b/src/CSharp/CodeCracker/packages.config deleted file mode 100644 index 28a6ce22f..000000000 --- a/src/CSharp/CodeCracker/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index f2b05c246..0ab0253ad 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -35,6 +35,15 @@ prompt 4 + + win + true + + + + + + @@ -56,11 +65,6 @@ - - - Designer - - ResXFileCodeGenerator @@ -71,51 +75,5 @@ Resources.Designer.cs - - - - - - - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - - - ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll - False - - - ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll - - - \ No newline at end of file diff --git a/src/Common/CodeCracker.Common/packages.config b/src/Common/CodeCracker.Common/packages.config deleted file mode 100644 index 324cafb10..000000000 --- a/src/Common/CodeCracker.Common/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index 31f867607..9a425da8f 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -9,6 +9,7 @@ Library CodeCracker.VisualBasic CodeCracker.VisualBasic + CodeCracker.VisualBasic.NewIdRequiredDueToNuGetBug en-US {14182A97-F7F0-4C62-8B27-98AA8AE2109A};{F184B08F-C81C-45F6-A57F-5ABD9991F28F} Profile7 @@ -54,12 +55,18 @@ On + + win + true + + + + + + - - Designer - PreserveNewest @@ -161,57 +168,5 @@ CodeCracker.Common - - - - - - - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.VisualBasic.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\portable-net45+win8\Microsoft.CodeAnalysis.Workspaces.dll - - - ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll - False - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll - False - - - ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll - - - \ No newline at end of file diff --git a/src/VisualBasic/CodeCracker/packages.config b/src/VisualBasic/CodeCracker/packages.config deleted file mode 100644 index 4ce3c94b7..000000000 --- a/src/VisualBasic/CodeCracker/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 4d186cfbe..5eef509d5 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -1,7 +1,5 @@  - - Debug AnyCPU @@ -41,76 +39,19 @@ false - - ..\..\..\packages\FluentAssertions.5.3.0\lib\net45\FluentAssertions.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll - - - ..\..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll - True - - - ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll - - - ..\..\..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll - - - ..\..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll - - - ..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - - ..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - - ..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll - + + + + + + @@ -199,9 +140,6 @@ - - Designer - @@ -227,27 +165,5 @@ - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/packages.config b/test/CSharp/CodeCracker.Test/packages.config deleted file mode 100644 index a23582940..000000000 --- a/test/CSharp/CodeCracker.Test/packages.config +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index 64b167733..0f296cd69 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -1,7 +1,5 @@  - - Debug @@ -37,82 +35,19 @@ 4 - - ..\..\..\packages\FluentAssertions.5.3.0\lib\net45\FluentAssertions.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll - - - ..\..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll - True - - - ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll - - - ..\..\..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll - - - ..\..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll - - - ..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - - ..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - - ..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll - + + + + + + @@ -125,32 +60,5 @@ - - - Designer - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/packages.config b/test/Common/CodeCracker.Test.Common/packages.config deleted file mode 100644 index eed89eef8..000000000 --- a/test/Common/CodeCracker.Test.Common/packages.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj index c5e096782..e27355417 100644 --- a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj +++ b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj @@ -1,7 +1,5 @@  - - Debug @@ -55,73 +53,16 @@ On - - ..\..\..\packages\FluentAssertions.5.3.0\lib\net45\FluentAssertions.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.3.2\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll - - - ..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll - - - ..\..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll - True - - - ..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll - True - - - ..\..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll - - - ..\..\..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll - - - ..\..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll - - - ..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - - ..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - - ..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll - + + + + + + @@ -195,9 +136,6 @@ My Settings.Designer.vb - - Designer - @@ -216,26 +154,5 @@ CodeCracker.Test.Common - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/packages.config b/test/VisualBasic/CodeCracker.Test/packages.config deleted file mode 100644 index e47b5ab69..000000000 --- a/test/VisualBasic/CodeCracker.Test/packages.config +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 0ed68e234dd4974239cd2bd963940068a90eb043 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 9 Sep 2018 23:51:54 -0500 Subject: [PATCH 204/234] Use DiagnosticResult from Microsoft.CodeAnalysis.Testing --- nuget.config | 2 + src/CSharp/CodeCracker/CodeCracker.csproj | 4 +- .../CodeCracker.Common.csproj | 2 +- .../CodeCracker/CodeCracker.vbproj | 4 +- .../CodeCracker.Test/CodeCracker.Test.csproj | 2 +- .../Design/MakeMethodStaticTests.cs | 31 +-- .../CodeCracker.Test/Design/NameOfTests.cs | 11 +- .../Design/StaticConstructorExceptionTests.cs | 11 +- .../Design/UseInvokeMethodToFireEventTests.cs | 201 ++++++------------ .../Maintainability/XmlDocumentationTests.cs | 21 +- .../Performance/EmptyFinalizerTests.cs | 31 +-- ...ocalVariablesConstWhenItIsPossibleTests.cs | 31 +-- .../RemoveWhereWhenItIsPossibleTests.cs | 11 +- .../Performance/SealedAttributeTests.cs | 21 +- .../Performance/StringBuilderInLoopTests.cs | 111 +++------- .../Performance/UseStaticRegexIsMatchTests.cs | 11 +- .../AddBracesToSwitchSectionsTests.cs | 31 +-- .../AllowMembersOrderingAnalyzerTests.cs | 11 +- .../Refactoring/ChangeAnyToAllTests.cs | 41 ++-- .../Refactoring/ComputeExpressionTests.cs | 11 +- .../Refactoring/InvertForTests.cs | 31 +-- .../Refactoring/MergeNestedIfTest.cs | 11 +- .../Refactoring/NumericLiteralTests.cs | 15 +- ...ngedEventArgsUnnecessaryAllocationTests.cs | 18 +- .../ReplaceWithGetterOnlyAutoPropertyTests.cs | 92 ++------ .../Refactoring/SplitIntoNestedIfTests.cs | 11 +- .../Refactoring/StringRepresentationTests.cs | 21 +- .../UseConfigureAwaitFalseTests.cs | 11 +- .../Style/AlwaysUseVarTests.cs | 31 +-- .../Style/ConsoleWriteLineTests.cs | 31 +-- ...nvertLambdaExpressionToMethodGroupTests.cs | 31 +-- .../ConvertToExpressionBodiedMemberTests.cs | 51 ++--- .../Style/ConvertToSwitchTests.cs | 21 +- .../Style/EmptyObjectInitializerTests.cs | 11 +- .../Style/ExistenceOperatorTests.cs | 21 +- .../CodeCracker.Test/Style/ForInArrayTests.cs | 71 ++----- .../Style/InterfaceNameTests.cs | 11 +- .../Style/ObjectInitializerTests.cs | 31 +-- .../Style/PropertyPrivateSetTests.cs | 11 +- .../Style/RemoveAsyncFromMethodTests.cs | 11 +- .../Style/RemoveCommentedCodeTests.cs | 21 +- .../Style/RemoveTrailingWhitespaceTests.cs | 12 +- .../Style/StringFormatTests.cs | 51 ++--- .../Style/SwitchToAutoPropTests.cs | 11 +- .../Style/TaskNameASyncTests.cs | 41 ++-- .../Style/TernaryOperatorTests.cs | 31 +-- .../Style/UnnecessaryParenthesisTests.cs | 11 +- ...ssaryToStringInStringConcatenationTests.cs | 13 +- .../Style/UseEmptyStringTest.cs | 15 +- .../Style/UseStringEmptyTests.cs | 41 ++-- ...stractClassShouldNotHavePublicCtorTests.cs | 11 +- .../Usage/ArgumentExceptionTests.cs | 51 ++--- .../CallExtensionMethodAsExtensionTests.cs | 61 ++---- .../Usage/DisposableFieldNotDisposedTests.cs | 111 +++------- .../DisposableVariableNotDisposedTests.cs | 101 +++------ ...posablesShouldCallSuppressFinalizeTests.cs | 21 +- .../Usage/IPAddressAnalyzerTests.cs | 10 +- .../Usage/IfReturnTrueTests.cs | 21 +- .../Usage/JsonNetAnalyzerTests.cs | 10 +- .../Usage/NoPrivateReadonlyFieldTest.cs | 15 +- .../Usage/ReadonlyFieldTests.cs | 171 +++++---------- .../Usage/RedundantFieldAssignmentTests.cs | 131 ++++-------- .../CodeCracker.Test/Usage/RegexTests.cs | 21 +- ...emovePrivateMethodNeverUsedAnalyzerTest.cs | 15 +- .../Usage/RemoveRedundantElseClauseTests.cs | 21 +- .../Usage/RethrowExceptionTests.cs | 11 +- ...implifyRedundantBooleanComparisonsTests.cs | 11 +- .../Usage/StringFormatArgsTests.cs | 81 +++---- .../Usage/UnusedParametersTests.cs | 11 +- .../Usage/UriAnalyzerTests.cs | 11 +- .../Usage/VirtualMethodOnConstructorTests.cs | 37 ++-- .../CodeCracker.Test.Common.csproj | 2 +- .../Helpers/DiagnosticResult.cs | 86 -------- .../Verifiers/DiagnosticVerifier.cs | 28 +-- .../CodeCracker.Test/CodeCracker.Test.vbproj | 2 +- .../CodeCracker.Test/Design/NameOfTests.vb | 11 +- .../Design/StaticConstructorExceptionTests.vb | 10 +- ...ocalVariablesConstWhenItIsPossibleTests.vb | 31 +-- .../RemoveWhereWhenItIsPossibleTests.vb | 11 +- .../Performance/SealedAttributeTests.vb | 21 +- .../Performance/StringBuilderInLoopTests.vb | 61 ++---- .../AllowMembersOrderingAnalyzerTests.vb | 10 +- .../Refactoring/ChangeAnyToAllTests.vb | 10 +- .../UseConfigureAwaitFalseTests.vb | 10 +- .../Style/InterfaceNameTests.vb | 10 +- .../Style/TernaryOperatorTests.vb | 28 +-- .../Usage/ArgumentExceptionTests.vb | 28 +-- .../Usage/DisposableFieldNotDisposedTests.vb | 111 +++------- ...posablesShouldCallSuppressFinalizeTests.vb | 19 +- .../Usage/IPAddressAnalyzerTests.vb | 9 +- .../Usage/JsonNetAnalyzerTests.vb | 10 +- ...lassShouldNotHavePublicConstructorTests.vb | 10 +- .../Usage/UnusedParametersTests.vb | 10 +- .../Usage/UriAnalyzerTests.vb | 10 +- 94 files changed, 910 insertions(+), 1949 deletions(-) delete mode 100644 test/Common/CodeCracker.Test.Common/Helpers/DiagnosticResult.cs diff --git a/nuget.config b/nuget.config index ffae90ba7..f42466e87 100644 --- a/nuget.config +++ b/nuget.config @@ -4,10 +4,12 @@ + + \ No newline at end of file diff --git a/src/CSharp/CodeCracker/CodeCracker.csproj b/src/CSharp/CodeCracker/CodeCracker.csproj index fdeef9f24..d81e8eee9 100644 --- a/src/CSharp/CodeCracker/CodeCracker.csproj +++ b/src/CSharp/CodeCracker/CodeCracker.csproj @@ -14,7 +14,7 @@ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Profile7 v4.5 - AD0001 + AD0001,RS1010,RS1016,RS1017,RS1022 true @@ -41,7 +41,7 @@ - + diff --git a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj index 0ab0253ad..8f502cca1 100644 --- a/src/Common/CodeCracker.Common/CodeCracker.Common.csproj +++ b/src/Common/CodeCracker.Common/CodeCracker.Common.csproj @@ -41,7 +41,7 @@ - + diff --git a/src/VisualBasic/CodeCracker/CodeCracker.vbproj b/src/VisualBasic/CodeCracker/CodeCracker.vbproj index 9a425da8f..877bee09b 100644 --- a/src/VisualBasic/CodeCracker/CodeCracker.vbproj +++ b/src/VisualBasic/CodeCracker/CodeCracker.vbproj @@ -14,7 +14,7 @@ {14182A97-F7F0-4C62-8B27-98AA8AE2109A};{F184B08F-C81C-45F6-A57F-5ABD9991F28F} Profile7 v4.5 - AD0001 + AD0001,RS1010,RS1016,RS1017,RS1022 true @@ -61,7 +61,7 @@ - + diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 5eef509d5..87c9508c5 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -49,7 +49,7 @@ - + diff --git a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs index 9a1590393..2d8829a4a 100644 --- a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Design; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -100,13 +101,9 @@ class C : I public async Task WithDiagnostic(string code) { var source = code.WrapInCSharpClass(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.MakeMethodStatic.ToDiagnosticId(), - Message = string.Format(MakeMethodStaticAnalyzer.MessageFormat, "Foo"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 18) } - }; + var expected = new DiagnosticResult(DiagnosticId.MakeMethodStatic.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 18) + .WithMessage(string.Format(MakeMethodStaticAnalyzer.MessageFormat, "Foo")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -1014,13 +1011,9 @@ public void M() } public static void N() { } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.MakeMethodStatic.ToDiagnosticId(), - Message = string.Format(MakeMethodStaticAnalyzer.MessageFormat, "M"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.MakeMethodStatic.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 17) + .WithMessage(string.Format(MakeMethodStaticAnalyzer.MessageFormat, "M")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -1053,13 +1046,9 @@ public void GetEnumerator() public static void N() { } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.MakeMethodStatic.ToDiagnosticId(), - Message = string.Format(MakeMethodStaticAnalyzer.MessageFormat, "GetEnumerator"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.MakeMethodStatic.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 17) + .WithMessage(string.Format(MakeMethodStaticAnalyzer.MessageFormat, "GetEnumerator")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Design/NameOfTests.cs b/test/CSharp/CodeCracker.Test/Design/NameOfTests.cs index 982738bef..819252585 100644 --- a/test/CSharp/CodeCracker.Test/Design/NameOfTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/NameOfTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Design; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -728,13 +729,9 @@ void Foo(TypeName d) private static DiagnosticResult CreateNameofDiagnosticResult(string nameofArgument, int diagnosticLine, int diagnosticColumn, DiagnosticId id = DiagnosticId.NameOf) { - return new DiagnosticResult - { - Id = id.ToDiagnosticId(), - Message = $"Use 'nameof({nameofArgument})' instead of specifying the program element name.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", diagnosticLine, diagnosticColumn) } - }; + return new DiagnosticResult(id.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(diagnosticLine, diagnosticColumn) + .WithMessage($"Use 'nameof({nameofArgument})' instead of specifying the program element name."); } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs b/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs index f6ba9d8a0..a8697697b 100644 --- a/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/StaticConstructorExceptionTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Design; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -19,13 +20,9 @@ static MyClass() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StaticConstructorException.ToDiagnosticId(), - Message = "Don't throw exceptions inside static constructors.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.StaticConstructorException.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 25) + .WithMessage("Don't throw exceptions inside static constructors."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs index f392107bc..90acb1bdd 100644 --- a/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/UseInvokeMethodToFireEventTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Design; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Design @@ -20,13 +21,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -45,13 +42,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -78,13 +71,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(16, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -111,13 +100,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(16, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -144,13 +129,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(16, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -178,13 +159,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(17, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -212,13 +189,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(17, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -237,13 +210,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -267,13 +236,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(13, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -298,13 +263,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(14, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -332,13 +293,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(17, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -366,13 +323,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(17, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -410,13 +363,9 @@ public class MyClass public void Execute() => MyEvent(this, System.EventArgs.Empty); }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -460,13 +409,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(13, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -492,13 +437,9 @@ public void Execute() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "MyEvent"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 15, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(15, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "MyEvent")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -548,13 +489,9 @@ public static void Execute(System.Action action) action(); } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "action"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "action")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -571,13 +508,9 @@ public static void Execute(System.Action action) action(); } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "action"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "action")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -593,13 +526,9 @@ public static void Execute(System.Action action) if (action == null) throw new Exception(); } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "action"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 25) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "action")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -683,13 +612,9 @@ public static void Execute(System.Action action) if (null == action) action(); }".WrapInCSharpClass(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "action"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 9) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(12, 9) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "action")); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -799,13 +724,9 @@ public static TReturn Method(System.Func getter) where T { return getter(default(T)); }".WrapInCSharpClass(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), - Message = string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat.ToString(), "getter"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 12) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseInvokeMethodToFireEvent.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(11, 12) + .WithMessage(string.Format(UseInvokeMethodToFireEventAnalyzer.MessageFormat, "getter")); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs b/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs index 4e060ac36..db37a35fa 100644 --- a/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs +++ b/test/CSharp/CodeCracker.Test/Maintainability/XmlDocumentationTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Maintainability; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -110,13 +111,9 @@ protected async static Task GetSortedDiagnosticsFromDocumentsAsync } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId(), - Message = "You have missing/unexistent parameters in Xml Docs", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 16) } - }; + var expected = new DiagnosticResult(DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 16) + .WithMessage("You have missing/unexistent parameters in Xml Docs"); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -141,13 +138,9 @@ public static Project CreateProject(string[] sources, out AdhocWorkspace workspa } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId(), - Message = "You have missing/unexistent parameters in Xml Docs", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 16) } - }; + var expected = new DiagnosticResult(DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 16) + .WithMessage("You have missing/unexistent parameters in Xml Docs"); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Performance/EmptyFinalizerTests.cs b/test/CSharp/CodeCracker.Test/Performance/EmptyFinalizerTests.cs index f86dde304..aef768752 100644 --- a/test/CSharp/CodeCracker.Test/Performance/EmptyFinalizerTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/EmptyFinalizerTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Performance; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -19,13 +20,9 @@ public class MyClass } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.EmptyFinalizer.ToDiagnosticId(), - Message = "Remove Empty Finalizers", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.EmptyFinalizer.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 21) + .WithMessage("Remove Empty Finalizers"); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -42,13 +39,9 @@ public class MyClass } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.EmptyFinalizer.ToDiagnosticId(), - Message = "Remove Empty Finalizers", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.EmptyFinalizer.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 21) + .WithMessage("Remove Empty Finalizers"); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -68,13 +61,9 @@ public class MyClass } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.EmptyFinalizer.ToDiagnosticId(), - Message = "Remove Empty Finalizers", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.EmptyFinalizer.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 21) + .WithMessage("Remove Empty Finalizers"); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs index e37f52a46..61b2311b3 100644 --- a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Performance; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -64,13 +65,9 @@ public async Task IgnoresPointerDeclarations() public async Task CreateDiagnosticsWhenAssigningAPotentialConstant() { var test = @"int a = 10;".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), - Message = "This variable can be made const.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 17) + .WithMessage("This variable can be made const."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -79,13 +76,9 @@ public async Task CreateDiagnosticsWhenAssigningAPotentialConstantInAVarDeclarat { var test = @"var a = 10;".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), - Message = "This variable can be made const.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 17) + .WithMessage("This variable can be made const."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -94,13 +87,9 @@ public async Task CreateDiagnosticsWhenAssigningNullToAReferenceType() { var test = @"Foo a = null;".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), - Message = "This variable can be made const.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 17) + .WithMessage("This variable can be made const."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs index c6e4b622a..64de3af7c 100644 --- a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Performance; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -32,13 +33,9 @@ public async Task DoSomething() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), - Message = "You can remove 'Where' moving the predicate to '" + method + "'.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(11, 23) + .WithMessage("You can remove 'Where' moving the predicate to '" + method + "'."); await VerifyCSharpDiagnosticAsync(test, expected); diff --git a/test/CSharp/CodeCracker.Test/Performance/SealedAttributeTests.cs b/test/CSharp/CodeCracker.Test/Performance/SealedAttributeTests.cs index e14f5e926..ce0fe3dfa 100644 --- a/test/CSharp/CodeCracker.Test/Performance/SealedAttributeTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/SealedAttributeTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Performance; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -16,13 +17,9 @@ public class MyAttribute : System.Attribute }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.SealedAttribute.ToDiagnosticId(), - Message = "Mark 'MyAttribute' as sealed.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 2, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.SealedAttribute.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(2, 30) + .WithMessage("Mark 'MyAttribute' as sealed."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -41,13 +38,9 @@ public class OtherAttribute : MyAttribute }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.SealedAttribute.ToDiagnosticId(), - Message = "Mark 'OtherAttribute' as sealed.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.SealedAttribute.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(7, 30) + .WithMessage("Mark 'OtherAttribute' as sealed."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs b/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs index 9f14bdcb5..75f557017 100644 --- a/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/StringBuilderInLoopTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -50,13 +51,9 @@ public async Task WhileWithStringConcatOnLocalVariableCreatesDiagnostic() { myString += """"; }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(14, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -78,13 +75,9 @@ public void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(11, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -107,13 +100,9 @@ public void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "MyString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(11, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "MyString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -128,20 +117,12 @@ public async Task WhileWithStringConcatWithSeveralConcatsOnDifferentVarsCreatesS myString1 += """"; myString2 += """"; }".WrapInCSharpMethod(); - var expected1 = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString1"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 15, 21) } - }; - var expected2 = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString2"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 21) } - }; + var expected1 = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(15, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString1")); + var expected2 = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(16, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString2")); await VerifyCSharpDiagnosticAsync(source, expected1, expected2); } @@ -154,13 +135,9 @@ public async Task WhileWithStringConcatWithSimpleAssignmentCreatesDiagnostic() { myString = myString + """"; }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(14, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -387,13 +364,9 @@ public async Task ForWithStringConcatOnLocalVariableCreatesDiagnostic() { myString += """"; }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(14, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -443,13 +416,9 @@ public async Task ForeachWithtStringConcatOnLocalVariableCreatesDiagnostic() { myString += """"; }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(14, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -483,13 +452,9 @@ public async Task DoWithtStringConcatOnLocalVariableCreatesDiagnostic() { myString += """"; } while (DateTime.Now.Second % 2 == 0);".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(14, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -537,13 +502,9 @@ public void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "someObject.A"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(16, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "someObject.A")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -570,13 +531,9 @@ public void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), - Message = string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "someObject.A[DateTime.Now.Second]"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 16, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringBuilderInLoop.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(16, 21) + .WithMessage(string.Format(StringBuilderInLoopAnalyzer.MessageFormat, "someObject.A[DateTime.Now.Second]")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs b/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs index c16424c06..5d4d8f76c 100644 --- a/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/UseStaticRegexIsMatchTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Performance; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -26,13 +27,9 @@ public async Task Foo() [Fact] public async Task CreatesDiagnosticsWhenDeclaringALocalRegexAndUsingIsMatch() { - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseStaticRegexIsMatch.ToDiagnosticId(), - Message = UseStaticRegexIsMatchAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseStaticRegexIsMatch.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(12, 17) + .WithMessage(UseStaticRegexIsMatchAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs index eab5fc7bb..9f8dfb62c 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Refactoring @@ -69,13 +70,9 @@ public async Task CreateDiagnosticWhenSingleSwitchSectionHasNoBraces() Foo(); break; }"; - var diagnostic = new DiagnosticResult - { - Id = DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), - Message = "Add braces for each section in this switch", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] {new DiagnosticResultLocation("Test0.cs", 10, 17)} - }; + var diagnostic = new DiagnosticResult(DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 17) + .WithMessage("Add braces for each section in this switch"); await VerifyCSharpDiagnosticAsync(test.WrapInCSharpMethod(), diagnostic); } @@ -98,13 +95,9 @@ public async Task CreateDiagnosticWhenNotAllSwitchSectionsHaveBraces() break; } }"; - var diagnostic = new DiagnosticResult - { - Id = DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), - Message = "Add braces for each section in this switch", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var diagnostic = new DiagnosticResult(DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 17) + .WithMessage("Add braces for each section in this switch"); await VerifyCSharpDiagnosticAsync(test.WrapInCSharpMethod(), diagnostic); } @@ -127,13 +120,9 @@ public async Task CreateDiagnosticWhenDefaultSectionsHasNoBraces() Baz(); break; }"; - var diagnostic = new DiagnosticResult - { - Id = DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), - Message = "Add braces for each section in this switch", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var diagnostic = new DiagnosticResult(DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 17) + .WithMessage("Add braces for each section in this switch"); await VerifyCSharpDiagnosticAsync(test.WrapInCSharpMethod(), diagnostic); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs index 724a2cfd6..bbede299f 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.cs @@ -1,6 +1,7 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Refactoring { @@ -50,13 +51,9 @@ public async void AllowMembersOrderingForMoreThanOneMemberShouldTriggerDiagnosti void car() { } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.AllowMembersOrdering.ToDiagnosticId(), - Message = AllowMembersOrderingAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 2, 14 + typeDeclaration.Length) } - }; + var expected = new DiagnosticResult(DiagnosticId.AllowMembersOrdering.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(2, 14 + typeDeclaration.Length) + .WithMessage(AllowMembersOrderingAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.cs index 5413edb7e..86ca15d52 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -29,13 +30,9 @@ public class ChangeAnyToAllTests : CodeFixVerifier i == 1); }} }}"; - var expected = new DiagnosticResult - { - Id = diagnosticId.ToDiagnosticId(), - Message = diagnosticId == DiagnosticId.ChangeAnyToAll ? ChangeAnyToAllAnalyzer.MessageAny : ChangeAnyToAllAnalyzer.MessageAll, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 43) } - }; + var expected = new DiagnosticResult(diagnosticId.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(13, 43) + .WithMessage(diagnosticId == DiagnosticId.ChangeAnyToAll ? ChangeAnyToAllAnalyzer.MessageAny : ChangeAnyToAllAnalyzer.MessageAll); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -246,13 +239,9 @@ class TypeName private System.Collections.Generic.IList xs; bool Foo() => xs.{methodName}(i => i == 1); }}"; - var expected = new DiagnosticResult - { - Id = diagnosticId.ToDiagnosticId(), - Message = diagnosticId == DiagnosticId.ChangeAnyToAll ? ChangeAnyToAllAnalyzer.MessageAny : ChangeAnyToAllAnalyzer.MessageAll, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 22) } - }; + var expected = new DiagnosticResult(diagnosticId.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(7, 22) + .WithMessage(diagnosticId == DiagnosticId.ChangeAnyToAll ? ChangeAnyToAllAnalyzer.MessageAny : ChangeAnyToAllAnalyzer.MessageAll); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -280,13 +269,9 @@ public async Task NegationWithCoalesceExpressionCreatesDiagnostic(string methodN var source = $@" var ints = new [] {{ 1 }}; var query = !ints?.{methodName}(i => i == 1) ?? true;"; - var expected = new DiagnosticResult - { - Id = diagnosticId.ToDiagnosticId(), - Message = diagnosticId == DiagnosticId.ChangeAnyToAll ? ChangeAnyToAllAnalyzer.MessageAny : ChangeAnyToAllAnalyzer.MessageAll, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 20) } - }; + var expected = new DiagnosticResult(diagnosticId.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(13, 20) + .WithMessage(diagnosticId == DiagnosticId.ChangeAnyToAll ? ChangeAnyToAllAnalyzer.MessageAny : ChangeAnyToAllAnalyzer.MessageAll); await VerifyCSharpDiagnosticAsync(source.WrapInCSharpMethod(usings: "\nusing System.Linq;"), expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs index e7a40762e..64f244a6c 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -38,13 +39,9 @@ public async Task BinaryExpressionWithLiteralOnLeftAndRightCreatesDiagnostic(str { var source = original.WrapInCSharpMethod(); var expression = original.Substring(columnOffset, original.Length - columnOffset - columnRightTrim - 1); - var expected = new DiagnosticResult - { - Id = DiagnosticId.ComputeExpression.ToDiagnosticId(), - Message = string.Format(ComputeExpressionAnalyzer.Message, expression), - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17 + columnOffset) } - }; + var expected = new DiagnosticResult(DiagnosticId.ComputeExpression.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 17 + columnOffset) + .WithMessage(string.Format(ComputeExpressionAnalyzer.Message, expression)); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/InvertForTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/InvertForTests.cs index 89bcb57b9..c46800685 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/InvertForTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/InvertForTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -125,13 +126,9 @@ public async Task CreateDiagnosticsWithForLoopsFrom0ToN() { var test = WrapInCSharpMethod(@"for (var i = 0; i < n; i++){}"); - var expected = new DiagnosticResult - { - Id = DiagnosticId.InvertFor.ToDiagnosticId(), - Message = "Make it a for loop that decrement the counter.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.InvertFor.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 17) + .WithMessage("Make it a for loop that decrement the counter."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -141,13 +138,9 @@ public async Task CreateDiagnosticsWithForLoopsTheUsesAnDeclaredVariableAsCounte { var test = WrapInCSharpMethod(@"int i = 0; for (i = 0; i < n; i++){}"); - var expected = new DiagnosticResult - { - Id = DiagnosticId.InvertFor.ToDiagnosticId(), - Message = "Make it a for loop that decrement the counter.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 28) } - }; + var expected = new DiagnosticResult(DiagnosticId.InvertFor.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 28) + .WithMessage("Make it a for loop that decrement the counter."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -157,13 +150,9 @@ public async Task CreateDiagnosticsWithForLoopsFromNTo0() { var test = WrapInCSharpMethod(@"for (var i = n - 1; i >= 0; i--){}"); - var expected = new DiagnosticResult - { - Id = DiagnosticId.InvertFor.ToDiagnosticId(), - Message = "Make it a for loop that increment the counter.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.InvertFor.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 17) + .WithMessage("Make it a for loop that increment the counter."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs b/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs index 1bcda1b72..32911a9f5 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/MergeNestedIfTest.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -39,13 +40,9 @@ public async Task NestedIfCreatesDiagnostic() var a = 1; } }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.MergeNestedIf.ToDiagnosticId(), - Message = MergeNestedIfAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.MergeNestedIf.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(11, 17) + .WithMessage(MergeNestedIfAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs index 74fce5482..feae0f6f6 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -80,13 +81,11 @@ void Foo() await VerifyCSharpFixAsync(source, fixtest); } - private static DiagnosticResult CreateDiagnosticResult(string literal, bool isDecimal, int row = 10, int col = 25) => - new DiagnosticResult - { - Id = DiagnosticId.NumericLiteral.ToDiagnosticId(), - Message = string.Format(NumericLiteralAnalyzer.Message, literal, isDecimal ? "hexadecimal" : "decimal"), - Severity = DiagnosticSeverity.Hidden, - Locations = new[] {new DiagnosticResultLocation("Test0.cs", row, col)} - }; + private static DiagnosticResult CreateDiagnosticResult(string literal, bool isDecimal, int row = 10, int col = 25) + { + return new DiagnosticResult(DiagnosticId.NumericLiteral.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(row, col) + .WithMessage(string.Format(NumericLiteralAnalyzer.Message, literal, isDecimal ? "hexadecimal" : "decimal")); + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs index 9e004869e..27fcfbb2f 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/PropertyChangedEventArgsUnnecessaryAllocationTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Collections.Generic; using System.Threading.Tasks; using Xunit; @@ -32,7 +33,7 @@ public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreatio { var source = $"var args = new PropertyChangedEventArgs({ctorArg})"; - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 12)); + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(1, 12)); } [Theory] @@ -57,7 +58,7 @@ public async Task DoesTriggerDiagnosticAtPropertyChangedEventArgsInstanceCreatio { var source = $"object args = new {{ Name = new PropertyChangedEventArgs({ctorArg}) }}"; - await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(0, 28)); + await VerifyCSharpDiagnosticAsync(source, PropertyChangedUnnecessaryAllocationDiagnostic(1, 28)); } [Theory] @@ -148,16 +149,9 @@ public void TestMethod(string propertyName) public static DiagnosticResult PropertyChangedUnnecessaryAllocationDiagnostic(int line, int column) { - return new DiagnosticResult - { - Id = DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId(), - Message = "Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] - { - new DiagnosticResultLocation("Test0.cs", line, column), - } - }; + return new DiagnosticResult(DiagnosticId.PropertyChangedEventArgsUnnecessaryAllocation.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(line, column) + .WithMessage("Create PropertyChangedEventArgs static instance and reuse it to avoid unecessary memory allocation."); } public static IEnumerable SharedDataCodeFix diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs index 072643c56..528ab9f0d 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ReplaceWithGetterOnlyAutoPropertyTests.cs @@ -1,6 +1,7 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -30,16 +31,9 @@ public async Task SimplePropertyGetsTransformed() public string Value { get { return _value; } } ".WrapInCSharpClass(); - var expected = new DiagnosticResult - { - Id = "CC0125", - Message = GetDiagnosticMessage("Value"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 16, 27) - } - }; + var expected = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(16, 27) + .WithMessage(GetDiagnosticMessage("Value")); await VerifyCSharpDiagnosticAsync(test, expected); @@ -83,16 +77,9 @@ public async Task FieldInitializerIsPreserved() public string Value { get { return this.value; } } ".WrapInCSharpClass(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("Value"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 16, 27) - } - }; + var expected = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(16, 27) + .WithMessage(GetDiagnosticMessage("Value")); await VerifyCSharpDiagnosticAsync(test, expected); @@ -125,26 +112,12 @@ public async Task MultiplePropertiesPerClassGetTranformed() public string Value2 { get { return this.value2; } } ".WrapInCSharpClass(); - var expected1 = new DiagnosticResult - { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("Value"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 17, 27) - } - }; - var expected2 = new DiagnosticResult - { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("Value2"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 18, 27) - } - }; + var expected1 = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(17, 27) + .WithMessage(GetDiagnosticMessage("Value")); + var expected2 = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(18, 27) + .WithMessage(GetDiagnosticMessage("Value2")); await VerifyCSharpDiagnosticAsync(test, new DiagnosticResult[] { expected1, expected2 }); @@ -176,26 +149,12 @@ public async Task MultiplePropertiesPerClassWithFieldInitilizerAndUnusedFieldsGe public string Value { get { return this.value; } } public string Value2 { get { return this.value2; } } ".WrapInCSharpClass(); - var expected1 = new DiagnosticResult - { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("Value"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 17, 27) - } - }; - var expected2 = new DiagnosticResult - { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("Value2"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 18, 27) - } - }; + var expected1 = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(17, 27) + .WithMessage(GetDiagnosticMessage("Value")); + var expected2 = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(18, 27) + .WithMessage(GetDiagnosticMessage("Value2")); await VerifyCSharpDiagnosticAsync(test, new DiagnosticResult[] { expected1, expected2 }); @@ -229,16 +188,9 @@ public async Task TypeOfPropertyMustFitTypeOfBackingField() public IEnumerable Value { get { return this.value; } } public IList Value2 { get { return this.value2; } } ".WrapInCSharpClass(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), - Message = GetDiagnosticMessage("Value2"), - Severity = DiagnosticSeverity.Hidden, - Locations = - new[] { - new DiagnosticResultLocation("Test0.cs", 18, 34) - } - }; + var expected = new DiagnosticResult(DiagnosticId.ReplaceWithGetterOnlyAutoProperty.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(18, 34) + .WithMessage(GetDiagnosticMessage("Value2")); await VerifyCSharpDiagnosticAsync(test, expected); diff --git a/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs index bf3507e67..b99818c1c 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -32,13 +33,9 @@ public async Task IfWithElseDoesNotCreateDiagnostic() public async Task IfWithAndCreatesDiagnostic() { var source = "if (true && true) { }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.SplitIntoNestedIf.ToDiagnosticId(), - Message = string.Format(SplitIntoNestedIfAnalyzer.Message), - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.SplitIntoNestedIf.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, 21) + .WithMessage(string.Format(SplitIntoNestedIfAnalyzer.Message)); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/StringRepresentationTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/StringRepresentationTests.cs index 8a97aca6f..d716b7a01 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/StringRepresentationTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/StringRepresentationTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Refactoring; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Xunit; @@ -55,13 +56,9 @@ void M() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringRepresentation_RegularString.ToDiagnosticId(), - Message = "Change to regular string", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringRepresentation_RegularString.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(6, 17) + .WithMessage("Change to regular string"); return VerifyCSharpDiagnosticAsync(source, expected); } @@ -77,13 +74,9 @@ void M() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringRepresentation_VerbatimString.ToDiagnosticId(), - Message = "Change to verbatim string", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringRepresentation_VerbatimString.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(6, 17) + .WithMessage("Change to verbatim string"); return VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs b/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs index b0aaf74ff..c8e981b55 100644 --- a/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs +++ b/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Reliability; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -18,13 +19,9 @@ public async Task WhenAwaitingTaskAnalyzerCreatesDiagnostic(string sample, int c { var test = sample.WrapInCSharpMethod(isAsync: true); - var expected = new DiagnosticResult - { - Id = DiagnosticId.UseConfigureAwaitFalse.ToDiagnosticId(), - Message = "Consider using ConfigureAwait(false) on the awaited task.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, column) } - }; + var expected = new DiagnosticResult(DiagnosticId.UseConfigureAwaitFalse.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(10, column) + .WithMessage("Consider using ConfigureAwait(false) on the awaited task."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/AlwaysUseVarTests.cs b/test/CSharp/CodeCracker.Test/Style/AlwaysUseVarTests.cs index d78489fbc..54f83e00d 100644 --- a/test/CSharp/CodeCracker.Test/Style/AlwaysUseVarTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/AlwaysUseVarTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Style; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -130,13 +131,9 @@ void Foo() dynamic Fee() { return 42; } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.AlwaysUseVar.ToDiagnosticId(), - Message = "Use 'var' instead of specifying the type name.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.AlwaysUseVar.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(9, 17) + .WithMessage("Use 'var' instead of specifying the type name."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -158,13 +155,9 @@ public async Task Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.AlwaysUseVarOnPrimitives.ToDiagnosticId(), - Message = "Use 'var' instead of specifying the type name.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.AlwaysUseVarOnPrimitives.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 17) + .WithMessage("Use 'var' instead of specifying the type name."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -187,13 +180,9 @@ public async Task Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.AlwaysUseVar.ToDiagnosticId(), - Message = "Use 'var' instead of specifying the type name.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.AlwaysUseVar.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 17) + .WithMessage("Use 'var' instead of specifying the type name."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/ConsoleWriteLineTests.cs b/test/CSharp/CodeCracker.Test/Style/ConsoleWriteLineTests.cs index 1335bc5df..ad678d592 100644 --- a/test/CSharp/CodeCracker.Test/Style/ConsoleWriteLineTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ConsoleWriteLineTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Style; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -174,13 +175,9 @@ void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConsoleWriteLine.ToDiagnosticId(), - Message = ConsoleWriteLineAnalyzer.MessageFormat.ToString(), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConsoleWriteLine.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(11, 17) + .WithMessage(ConsoleWriteLineAnalyzer.MessageFormat.ToString()); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -200,13 +197,9 @@ void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConsoleWriteLine.ToDiagnosticId(), - Message = ConsoleWriteLineAnalyzer.MessageFormat.ToString(), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConsoleWriteLine.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 17) + .WithMessage(ConsoleWriteLineAnalyzer.MessageFormat.ToString()); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -404,13 +397,9 @@ void Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConsoleWriteLine.ToDiagnosticId(), - Message = ConsoleWriteLineAnalyzer.MessageFormat.ToString(), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConsoleWriteLine.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(11, 17) + .WithMessage(ConsoleWriteLineAnalyzer.MessageFormat.ToString()); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs b/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs index b82e826f1..0a968adf9 100644 --- a/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Style; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -12,13 +13,9 @@ public class ConvertLambdaExpressionToMethodGroupTests public async Task CreateDiagnosticForSimpleLambdaExpression() { const string test = @"var f = a.Where(item => filter(item));"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertLambdaExpressionToMethodGroup.ToDiagnosticId(), - Message = "You should remove the lambda expression and pass just 'filter' instead.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 1, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertLambdaExpressionToMethodGroup.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(1, 17) + .WithMessage("You should remove the lambda expression and pass just 'filter' instead."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -27,13 +24,9 @@ public async Task CreateDiagnosticForSimpleLambdaExpression() public async Task CreateDiagnosticForSimpleLambdaExpressionWithBlockInBody() { const string test = @"var f = a.Where(item => { return filter(item); });"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertLambdaExpressionToMethodGroup.ToDiagnosticId(), - Message = "You should remove the lambda expression and pass just 'filter' instead.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 1, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertLambdaExpressionToMethodGroup.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(1, 17) + .WithMessage("You should remove the lambda expression and pass just 'filter' instead."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -42,13 +35,9 @@ public async Task CreateDiagnosticForSimpleLambdaExpressionWithBlockInBody() public async Task CreateDiagnosticForParenthesizedLambdaExpressionWithBlockInBody() { const string test = @"var f = a.Foo((param1, param2) => { return filter(param1, param2); });"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertLambdaExpressionToMethodGroup.ToDiagnosticId(), - Message = "You should remove the lambda expression and pass just 'filter' instead.", - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 1, 15) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertLambdaExpressionToMethodGroup.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(1, 15) + .WithMessage("You should remove the lambda expression and pass just 'filter' instead."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/ConvertToExpressionBodiedMemberTests.cs b/test/CSharp/CodeCracker.Test/Style/ConvertToExpressionBodiedMemberTests.cs index 331b8282a..ef0170df5 100644 --- a/test/CSharp/CodeCracker.Test/Style/ConvertToExpressionBodiedMemberTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ConvertToExpressionBodiedMemberTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Style; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -177,13 +178,9 @@ public async Task Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), - Message = ConvertToExpressionBodiedMemberAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 13) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(8, 13) + .WithMessage(ConvertToExpressionBodiedMemberAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -204,13 +201,9 @@ class TypeName } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), - Message = ConvertToExpressionBodiedMemberAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 13) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(8, 13) + .WithMessage(ConvertToExpressionBodiedMemberAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -231,13 +224,9 @@ public static implicit operator string(TypeName n) } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), - Message = ConvertToExpressionBodiedMemberAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 13) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(8, 13) + .WithMessage(ConvertToExpressionBodiedMemberAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -258,13 +247,9 @@ public Foo this[int id] } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), - Message = ConvertToExpressionBodiedMemberAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 13) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(8, 13) + .WithMessage(ConvertToExpressionBodiedMemberAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -285,13 +270,9 @@ public string Foo } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), - Message = ConvertToExpressionBodiedMemberAnalyzer.MessageFormat, - Severity = DiagnosticSeverity.Hidden, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 13) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToExpressionBodiedMember.ToDiagnosticId(), DiagnosticSeverity.Hidden) + .WithLocation(8, 13) + .WithMessage(ConvertToExpressionBodiedMemberAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/ConvertToSwitchTests.cs b/test/CSharp/CodeCracker.Test/Style/ConvertToSwitchTests.cs index b4fb48bf0..bcdb5d47d 100644 --- a/test/CSharp/CodeCracker.Test/Style/ConvertToSwitchTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ConvertToSwitchTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Style; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -38,13 +39,9 @@ public async Task Foo(string s) } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToSwitch.ToDiagnosticId(), - Message = "You could use 'switch' instead of 'if'.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToSwitch.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 17) + .WithMessage("You could use 'switch' instead of 'if'."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -76,13 +73,9 @@ public async Task Foo(string s) } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ConvertToSwitch.ToDiagnosticId(), - Message = "You could use 'switch' instead of 'if'.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ConvertToSwitch.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 17) + .WithMessage("You could use 'switch' instead of 'if'."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs b/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs index 129824e22..2c978823b 100644 --- a/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/EmptyObjectInitializerTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Style; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -11,13 +12,9 @@ public class EmptyObjectInitializerTests : CodeFixVerifier action = (p) => { throw new ArgumentException(""message"", ""paramName""); }; "); - var expected = new DiagnosticResult - { - Id = DiagnosticId.ArgumentException.ToDiagnosticId(), - Message = "Type argument 'paramName' is not in the argument list.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 82) } - }; + var expected = new DiagnosticResult(DiagnosticId.ArgumentException.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(9, 82) + .WithMessage("Type argument 'paramName' is not in the argument list."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs b/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs index 31de8f5c7..07d98a122 100644 --- a/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/CallExtensionMethodAsExtensionTests.cs @@ -1,6 +1,7 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -64,13 +65,9 @@ public void Bar() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), - Message = "Do not call 'Any' method of class 'Enumerable' as a static method", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 33) + .WithMessage("Do not call 'Any' method of class 'Enumerable' as a static method"); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -91,13 +88,9 @@ public void Bar() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), - Message = "Do not call 'Any' method of class 'Enumerable' as a static method", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 33) + .WithMessage("Do not call 'Any' method of class 'Enumerable' as a static method"); await VerifyCSharpDiagnosticAsync(source, expected, LanguageVersion.CSharp5); } @@ -116,13 +109,9 @@ public static class C { public static string M(this string s) => s; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), - Message = "Do not call 'M' method of class 'C' as a static method", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 9) } - }; + var expected = new DiagnosticResult(DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 9) + .WithMessage("Do not call 'M' method of class 'C' as a static method"); await VerifyCSharpDiagnosticAsync(source, expected, LanguageVersion.CSharp5); } @@ -142,13 +131,9 @@ public void Bar() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), - Message = "Do not call 'Any' method of class 'Enumerable' as a static method", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(9, 33) + .WithMessage("Do not call 'Any' method of class 'Enumerable' as a static method"); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -358,13 +343,9 @@ public void Bar() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), - Message = "Do not call 'Any' method of class 'Enumerable' as a static method", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 37) } - }; + var expected = new DiagnosticResult(DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(11, 37) + .WithMessage("Do not call 'Any' method of class 'Enumerable' as a static method"); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -383,13 +364,9 @@ public class Foo } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), - Message = "Do not call 'Any' method of class 'Enumerable' as a static method", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 51) } - }; + var expected = new DiagnosticResult(DiagnosticId.CallExtensionMethodAsExtension.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(8, 51) + .WithMessage("Do not call 'Any' method of class 'Enumerable' as a static method"); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs index 1c46e93f2..2337557a8 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -85,13 +86,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -131,20 +128,12 @@ class D : IDisposable public void Dispose() { } } }"; - var expected1 = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field1"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; - var expected2 = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field2"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 41) } - }; + var expected1 = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field1")); + var expected2 = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 41) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field2")); await VerifyCSharpDiagnosticAsync(source, expected1, expected2); } @@ -169,13 +158,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -199,13 +184,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -297,13 +278,9 @@ struct D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -328,13 +305,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -360,13 +333,9 @@ public void Dispose() { } public void Dispose(bool arg) { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -392,13 +361,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -418,13 +383,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(7, 23) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -445,13 +406,9 @@ class D : IDisposable public void Dispose() { } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - Message = string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 33) + .WithMessage(string.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index cb1437596..daad3e39a 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -157,13 +158,9 @@ public async Task IteratorWithIndirectReturnDoesNotCreateDiagnostic() public async Task DisposableVariableCreatesDiagnostic() { var source = "new System.IO.MemoryStream();".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 17) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -178,13 +175,9 @@ public async Task IgnoresDisposableObjectsCreatedWithUsingStatement() public async Task DisposableVariableDeclaredWithAnotherVariableCreatesOnlyOneDiagnostic() { var source = "System.IO.MemoryStream a, b = new System.IO.MemoryStream();".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 47) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 47) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -336,13 +329,9 @@ static void Foo() void Register(System.Action f) { } } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 34) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(7, 34) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -362,13 +351,9 @@ static void Foo() void Register(System.Action f) { } } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 32) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 32) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -388,13 +373,9 @@ static void Foo() void Register(System.Action f) { } } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 32) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 32) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -414,13 +395,9 @@ static void Foo() void Register(System.Action f) { } } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 32) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(8, 32) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -468,13 +445,9 @@ void System.IDisposable.Dispose() { } public async Task DisposableVariablePassedAsParamCreatesDiagnostic() { var source = "string.Format(\"\", new System.IO.MemoryStream());".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 35) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 35) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -483,13 +456,9 @@ public async Task DisposableVariableCallsIncorrectDisposeCreatesDiagnostic() { var source = @"var m = new System.IO.MemoryStream(); m.Dispose(true);".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 25) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -511,13 +480,9 @@ void System.IDisposable.Dispose() { } public void Dispose() { } } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "Disposable"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 33) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "Disposable")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -563,13 +528,9 @@ void System.IDisposable.Dispose() { } void IOtherDisposable.Dispose() { } } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), - Message = string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "Disposable"), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 33) + .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "Disposable")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs index 487f2b557..437626d9d 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -57,13 +58,9 @@ public void Dispose() } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), - Message = "'MyType' should call GC.SuppressFinalize inside the Dispose method.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 33) + .WithMessage("'MyType' should call GC.SuppressFinalize inside the Dispose method."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -263,13 +260,9 @@ public void Dispose() ~MyType() {} }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), - Message = "'MyType' should call GC.SuppressFinalize inside the Dispose method.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(4, 33) + .WithMessage("'MyType' should call GC.SuppressFinalize inside the Dispose method."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/IPAddressAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Usage/IPAddressAnalyzerTests.cs index ccf94d7e4..ca83c566c 100644 --- a/test/CSharp/CodeCracker.Test/Usage/IPAddressAnalyzerTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/IPAddressAnalyzerTests.cs @@ -4,6 +4,7 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -78,12 +79,9 @@ public async Task IfAbbreviateParseIdentifierFoundAndParameterIsNotStringLiteral private static DiagnosticResult CreateDiagnosticResult(int line, int column, Action getErrorMessageAction) { - return new DiagnosticResult { - Id = DiagnosticId.IPAddress.ToDiagnosticId(), - Message = GetErrorMessage(getErrorMessageAction), - Severity = DiagnosticSeverity.Error, - Locations = new[] {new DiagnosticResultLocation("Test0.cs", line, column)} - }; + return new DiagnosticResult(DiagnosticId.IPAddress.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(line, column) + .WithMessage(GetErrorMessage(getErrorMessageAction)); } private static string GetErrorMessage(Action action) diff --git a/test/CSharp/CodeCracker.Test/Usage/IfReturnTrueTests.cs b/test/CSharp/CodeCracker.Test/Usage/IfReturnTrueTests.cs index f45326646..27b4ad1f0 100644 --- a/test/CSharp/CodeCracker.Test/Usage/IfReturnTrueTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/IfReturnTrueTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -153,13 +154,9 @@ public int Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.IfReturnTrue.ToDiagnosticId(), - Message = "You should return the boolean directly.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.IfReturnTrue.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(9, 17) + .WithMessage("You should return the boolean directly."); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -186,13 +183,9 @@ public int Foo() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.IfReturnTrue.ToDiagnosticId(), - Message = "You should return the boolean directly.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.IfReturnTrue.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(9, 17) + .WithMessage("You should return the boolean directly."); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs index d94b0be0b..32b49198b 100644 --- a/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/JsonNetAnalyzerTests.cs @@ -2,6 +2,7 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -94,12 +95,9 @@ public async Task IfJArrayParseIdentifierFoundAndJsonTextIsCorrectDoesNotCreates } private static DiagnosticResult CreateDiagnosticResult(int line, int column) { - return new DiagnosticResult { - Id = DiagnosticId.JsonNet.ToDiagnosticId(), - Message = "Unexpected end when reading JSON. Path '', line 1, position 3.", - Severity = DiagnosticSeverity.Error, - Locations = new[] {new DiagnosticResultLocation("Test0.cs", line, column)} - }; + return new DiagnosticResult(DiagnosticId.JsonNet.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(line, column) + .WithMessage("Unexpected end when reading JSON. Path '', line 1, position 3."); } protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() => new JsonNetAnalyzer(); diff --git a/test/CSharp/CodeCracker.Test/Usage/NoPrivateReadonlyFieldTest.cs b/test/CSharp/CodeCracker.Test/Usage/NoPrivateReadonlyFieldTest.cs index 2c707711a..f1fb1e715 100644 --- a/test/CSharp/CodeCracker.Test/Usage/NoPrivateReadonlyFieldTest.cs +++ b/test/CSharp/CodeCracker.Test/Usage/NoPrivateReadonlyFieldTest.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Xunit; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; namespace CodeCracker.Test.CSharp.Usage { @@ -10,14 +11,12 @@ public class NoPrivateReadonlyFieldTests : CodeFixVerifier { protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() => new NoPrivateReadonlyFieldAnalyzer(); - static DiagnosticResult CreateExpectedDiagnosticResult(int line, int column, string fieldName = "i") => - new DiagnosticResult - { - Id = DiagnosticId.NoPrivateReadonlyField.ToDiagnosticId(), - Message = string.Format(NoPrivateReadonlyFieldAnalyzer.Message, fieldName), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", line, column) } - }; + static DiagnosticResult CreateExpectedDiagnosticResult(int line, int column, string fieldName = "i") + { + return new DiagnosticResult(DiagnosticId.NoPrivateReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(line, column) + .WithMessage(string.Format(NoPrivateReadonlyFieldAnalyzer.Message, fieldName)); + } [Fact] public async Task PrivateFieldWithAssignmentOnDeclarationCreatesNoDiagnostic() diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index e49637973..8639541c5 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -182,13 +183,9 @@ class TypeName private int i = 1; } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -203,13 +200,9 @@ class TypeName int i = 1; } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 17) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -225,20 +218,12 @@ class TypeName private int j = 1; } }"; - var expected1 = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; - var expected2 = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "j"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 25) } - }; + var expected1 = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); + var expected2 = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "j")); await VerifyCSharpDiagnosticAsync(source, expected1, expected2); } @@ -259,34 +244,18 @@ class TypeName2 private int l = 1; } }"; - var expected1 = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; - var expected2 = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "j"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 25) } - }; - var expected3 = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "k"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 25) } - }; - var expected4 = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "l"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 25) } - }; + var expected1 = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); + var expected2 = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(7, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "j")); + var expected3 = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(11, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "k")); + var expected4 = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(12, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "l")); await VerifyCSharpDiagnosticAsync(source, new[] { expected1, expected2, expected3, expected4 }); } @@ -304,13 +273,9 @@ class TypeName } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 8, 29) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(8, 29) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -325,13 +290,9 @@ struct TypeName private int i = 1; } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -401,13 +362,9 @@ class TypeName } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -426,13 +383,9 @@ class TypeName } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 25) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -491,13 +444,9 @@ class TypeName private int i, j = 1; } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "j"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 28) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 28) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "j")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -747,13 +696,9 @@ static TypeName() } } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 32) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 32) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -768,13 +713,9 @@ class TypeName private static int i = 1; } }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "i"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 32) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 32) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "i")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -953,13 +894,9 @@ private enum VehicleType } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "car"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 33) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "car")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -981,13 +918,9 @@ public Person(string name) } "; - var expected = new DiagnosticResult - { - Id = DiagnosticId.ReadonlyField.ToDiagnosticId(), - Message = string.Format(ReadonlyFieldAnalyzer.Message, "name"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 28) } - }; + var expected = new DiagnosticResult(DiagnosticId.ReadonlyField.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(6, 28) + .WithMessage(string.Format(ReadonlyFieldAnalyzer.Message, "name")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/RedundantFieldAssignmentTests.cs b/test/CSharp/CodeCracker.Test/Usage/RedundantFieldAssignmentTests.cs index 97caea241..f24ccfc5b 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RedundantFieldAssignmentTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RedundantFieldAssignmentTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -170,13 +171,9 @@ class TypeName { private int i = 0; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", 0), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 17) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", 0)); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -188,13 +185,9 @@ class TypeName { private int i = default(int); }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "default(int)"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 17) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "default(int)")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -206,13 +199,9 @@ class TypeName { private string s = null; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "s", "null"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 20) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 20) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "s", "null")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -224,13 +213,9 @@ class TypeName { private long i = 0L; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "0L"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 18) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 18) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "0L")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -242,13 +227,9 @@ class TypeName { private long i = 0; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "0"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 18) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 18) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "0")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -260,13 +241,9 @@ class TypeName { private System.IntPtr i = System.IntPtr.Zero; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "System.IntPtr.Zero"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 27) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 27) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "System.IntPtr.Zero")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -279,13 +256,9 @@ class TypeName { private IntPtr i = IntPtr.Zero; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "IntPtr.Zero"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 20) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(5, 20) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "IntPtr.Zero")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -297,13 +270,9 @@ class TypeName { private System.UIntPtr i = System.UIntPtr.Zero; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "System.UIntPtr.Zero"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 28) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 28) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "i", "System.UIntPtr.Zero")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -315,13 +284,9 @@ class TypeName { private System.DateTime d = System.DateTime.MinValue; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "d", "System.DateTime.MinValue"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 29) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 29) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "d", "System.DateTime.MinValue")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -334,13 +299,9 @@ class TypeName { private E e = 0; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "e", "0"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 15) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(5, 15) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "e", "0")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -353,13 +314,9 @@ class TypeName { private E e = 0.0; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "e", "0.0"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 15) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(5, 15) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "e", "0.0")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -371,13 +328,9 @@ class TypeName { private bool b = false; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "b", "false"), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 18) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 18) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "b", "false")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -389,13 +342,9 @@ class TypeName { private int i, j, k = 0; }"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), - Message = string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "k", 0), - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 23) } - }; + var expected = new DiagnosticResult(DiagnosticId.RedundantFieldAssignment.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(4, 23) + .WithMessage(string.Format(RedundantFieldAssignmentAnalyzer.MessageFormat, "k", 0)); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/RegexTests.cs b/test/CSharp/CodeCracker.Test/Usage/RegexTests.cs index 6ffda204c..8feee163a 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RegexTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RegexTests.cs @@ -1,6 +1,7 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using System; using System.Threading.Tasks; using Xunit; @@ -76,13 +77,9 @@ public async Task Foo() message = e.Message; } - var expected = new DiagnosticResult - { - Id = DiagnosticId.Regex.ToDiagnosticId(), - Message = message, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 64) } - }; + var expected = new DiagnosticResult(DiagnosticId.Regex.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(11, 64) + .WithMessage(message); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -116,13 +113,9 @@ public async Task Foo() message = e.Message; } - var expected = new DiagnosticResult - { - Id = DiagnosticId.Regex.ToDiagnosticId(), - Message = message, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 33) } - }; + var expected = new DiagnosticResult(DiagnosticId.Regex.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(11, 33) + .WithMessage(message); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs b/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs index 3c5383c1e..ee42e29a9 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RemovePrivateMethodNeverUsedAnalyzerTest.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -427,14 +428,12 @@ public int PropertyXXX { await VerifyCSharpHasNoDiagnosticsAsync(source); } - private static DiagnosticResult CreateDiagnosticResult(int line, int column) => - new DiagnosticResult - { - Id = DiagnosticId.RemovePrivateMethodNeverUsed.ToDiagnosticId(), - Locations = new DiagnosticResultLocation[] { new DiagnosticResultLocation("Test0.cs", line, column) }, - Message = RemovePrivateMethodNeverUsedAnalyzer.Message, - Severity = DiagnosticSeverity.Info, - }; + private static DiagnosticResult CreateDiagnosticResult(int line, int column) + { + return new DiagnosticResult(DiagnosticId.RemovePrivateMethodNeverUsed.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(line, column) + .WithMessage(RemovePrivateMethodNeverUsedAnalyzer.Message); + } [Fact] public async void WinFormsPropertyDefaultValueDefinitionMethodsMustHaveCorrectSignature() diff --git a/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs b/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs index 82904f6f5..9849a0655 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -120,13 +121,9 @@ public async Task CreateDiagnosticsWhenEmptyElse() { var test = @"if(1 == 2){ return 1; } else { }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.RemoveRedundantElseClause.ToDiagnosticId(), - Message = "Remove redundant else", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 41) } - }; + var expected = new DiagnosticResult(DiagnosticId.RemoveRedundantElseClause.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 41) + .WithMessage("Remove redundant else"); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -136,13 +133,9 @@ public async Task CreateDiagnosticsWhenEmptyElseWithoutBlockOnIf() { var test = @"if(1 == 2) return 1; else { }".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.RemoveRedundantElseClause.ToDiagnosticId(), - Message = "Remove redundant else", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 38) } - }; + var expected = new DiagnosticResult(DiagnosticId.RemoveRedundantElseClause.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, 38) + .WithMessage("Remove redundant else"); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs b/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs index 4bec3f3fd..f32efd7e2 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RethrowExceptionTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -27,13 +28,9 @@ public void Foo() [Fact] public async Task WhenThrowingOriginalExceptionAnalyzerCreatesDiagnostic() { - var expected = new DiagnosticResult - { - Id = DiagnosticId.RethrowException.ToDiagnosticId(), - Message = "Throwing the same exception that was caught will lose the original stack trace.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 21) } - }; + var expected = new DiagnosticResult(DiagnosticId.RethrowException.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(12, 21) + .WithMessage("Throwing the same exception that was caught will lose the original stack trace."); await VerifyCSharpDiagnosticAsync(sourceWithUsingSystem, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs b/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs index 714e2bc3c..b1fa44b3f 100644 --- a/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -31,13 +32,9 @@ public async Task WhenComparingWithBoolAnalyzerCreatesDiagnostic(string sample, column += 10; // adjust column for added declaration var test = sample.WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.SimplifyRedundantBooleanComparisons.ToDiagnosticId(), - Message = "You can remove this comparison.", - Severity = DiagnosticSeverity.Info, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, column) } - }; + var expected = new DiagnosticResult(DiagnosticId.SimplifyRedundantBooleanComparisons.ToDiagnosticId(), DiagnosticSeverity.Info) + .WithLocation(10, column) + .WithMessage("You can remove this comparison."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs b/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs index 5b6cf0257..b5ffbb6e9 100644 --- a/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs @@ -3,6 +3,7 @@ using Xunit; using Microsoft.CodeAnalysis.Diagnostics; using CodeCracker.CSharp.Usage; +using Microsoft.CodeAnalysis.Testing; namespace CodeCracker.Test.CSharp.Usage { @@ -82,13 +83,9 @@ public async Task IgnoresMethodsCalledWithIncorrectParameterTypes() public async Task NoParametersCreatesError() { var source = @"var result = string.Format(""{0}"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.InvalidArgsReferenceMessage, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(10, 30) + .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -96,13 +93,9 @@ public async Task NoParametersCreatesError() public async Task LessParametersCreatesError() { var source = @"var result = string.Format(""one {0} two {1}"", ""a"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.InvalidArgsReferenceMessage, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(10, 30) + .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -110,13 +103,9 @@ public async Task LessParametersCreatesError() public async Task MoreArgumentsCreatesWarning() { var source = @"var result = string.Format(""one {0} two {1}"", ""a"", ""b"", ""c"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 30) + .WithMessage(StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -145,13 +134,9 @@ public async Task MethodWithParamtersReferencingSingleAndFormatSpecifiersArgumen public async Task TwoParametersReferencingSamePlaceholderCreatesWarning() { var source = @"var result = string.Format(""one {0} two {0}"", ""a"", ""b"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 30) + .WithMessage(StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -183,13 +168,9 @@ public async Task VerbatimStringWithMissingArgCreatesError() var noun = ""Giovanni""; var s = string.Format(@""This {0} is """"{1}""""."", noun);".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.InvalidArgsReferenceMessage, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 25) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(12, 25) + .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -197,13 +178,9 @@ public async Task VerbatimStringWithMissingArgCreatesError() public async Task InvalidArgumentReferenceCreatesError() { var source = @"var result = string.Format(""one {1}"", ""a"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.InvalidArgsReferenceMessage, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(10, 30) + .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -211,13 +188,9 @@ public async Task InvalidArgumentReferenceCreatesError() public async Task NonIntegerPlaceholderCreatesError() { var source = @"var result = string.Format(""one {notZero}"", ""a"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.InvalidArgsReferenceMessage, - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 30) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(10, 30) + .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -225,13 +198,9 @@ public async Task NonIntegerPlaceholderCreatesError() public async Task UnusedArgsCreatesWarning() { var source = @"string.Format(""{0}{1}{3}{5}"", ""a"", ""b"", ""c"", ""d"", ""e"", ""f"");".WrapInCSharpMethod(); - var expected = new DiagnosticResult - { - Id = DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), - Message = StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 17) } - }; + var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(10, 17) + .WithMessage(StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage); await VerifyCSharpDiagnosticAsync(source, expected); } } diff --git a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs index 2b08add48..2bee868b0 100644 --- a/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/UnusedParametersTests.cs @@ -1,5 +1,6 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; using System.Threading.Tasks; using Xunit; @@ -330,13 +331,9 @@ await VerifyCSharpDiagnosticAsync(source, public static DiagnosticResult CreateDiagnosticResult(string parameterName, int line, int column) { - return new DiagnosticResult - { - Id = DiagnosticId.UnusedParameters.ToDiagnosticId(), - Message = string.Format(UnusedParametersAnalyzer.Message, parameterName), - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", line, column) } - }; + return new DiagnosticResult(DiagnosticId.UnusedParameters.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(line, column) + .WithMessage(string.Format(UnusedParametersAnalyzer.Message, parameterName)); } [Fact] diff --git a/test/CSharp/CodeCracker.Test/Usage/UriAnalyzerTests.cs b/test/CSharp/CodeCracker.Test/Usage/UriAnalyzerTests.cs index 8a947ea9a..e48b9a1f8 100644 --- a/test/CSharp/CodeCracker.Test/Usage/UriAnalyzerTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/UriAnalyzerTests.cs @@ -3,6 +3,7 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Usage @@ -93,13 +94,9 @@ public void Test() { private static DiagnosticResult CreateDiagnosticResult(int line, int column, Action getErrorMessageAction) { - return new DiagnosticResult - { - Id = DiagnosticId.Uri.ToDiagnosticId(), - Message = GetErrorMessage(getErrorMessageAction), - Severity = DiagnosticSeverity.Error, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", line, column) } - }; + return new DiagnosticResult(DiagnosticId.Uri.ToDiagnosticId(), DiagnosticSeverity.Error) + .WithLocation(line, column) + .WithMessage(GetErrorMessage(getErrorMessageAction)); } private static string GetErrorMessage(Action action) diff --git a/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs b/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs index 6d55294df..1c3800de0 100644 --- a/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/VirtualMethodOnConstructorTests.cs @@ -2,6 +2,7 @@ using CodeCracker.CSharp.Usage; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace CodeCracker.Test.CSharp.Usage { @@ -21,12 +22,9 @@ public virtual void DoFoo(string foo) { } }"; - var expected = new DiagnosticResult { - Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), - Message = VirtualMethodOnConstructorAnalyzer.Message, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 3) } - }; + var expected = new DiagnosticResult(DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 3) + .WithMessage(VirtualMethodOnConstructorAnalyzer.Message); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -45,12 +43,9 @@ public virtual void DoFoo(string foo) { } }"; - var expected = new DiagnosticResult { - Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), - Message = VirtualMethodOnConstructorAnalyzer.Message, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 3) } - }; + var expected = new DiagnosticResult(DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 3) + .WithMessage(VirtualMethodOnConstructorAnalyzer.Message); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -110,18 +105,12 @@ public virtual void DoFoo2(string foo) { } }"; - var expected = new DiagnosticResult { - Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), - Message = VirtualMethodOnConstructorAnalyzer.Message, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 3) } - }; - var expected2 = new DiagnosticResult { - Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), - Message = VirtualMethodOnConstructorAnalyzer.Message, - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 3) } - }; + var expected = new DiagnosticResult(DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(6, 3) + .WithMessage(VirtualMethodOnConstructorAnalyzer.Message); + var expected2 = new DiagnosticResult(DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), DiagnosticSeverity.Warning) + .WithLocation(7, 3) + .WithMessage(VirtualMethodOnConstructorAnalyzer.Message); await VerifyCSharpDiagnosticAsync(test, expected, expected2); } diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index 0f296cd69..db5e82f6f 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -44,6 +44,7 @@ + @@ -53,7 +54,6 @@ - diff --git a/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticResult.cs b/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticResult.cs deleted file mode 100644 index 46d38366e..000000000 --- a/test/Common/CodeCracker.Test.Common/Helpers/DiagnosticResult.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Microsoft.CodeAnalysis; -using System; - -namespace CodeCracker.Test -{ - /// - /// Location where the diagnostic appears, as determined by path, line number, and column number. - /// - public struct DiagnosticResultLocation - { - public DiagnosticResultLocation(string path, int line, int column) - { - if (line < 0 && column < 0) - { - throw new ArgumentOutOfRangeException("At least one of line and column must be > 0"); - } - if (line < -1 || column < -1) - { - throw new ArgumentOutOfRangeException("Both line and column must be >= -1"); - } - - Path = path; - Line = line; - Column = column; - } - - public string Path { get; set; } - public int Line { get; set; } - public int Column { get; set; } - } - - /// - /// Struct that stores information about a Diagnostic appearing in a source - /// - public struct DiagnosticResult - { - private DiagnosticResultLocation[] locations; - - public DiagnosticResultLocation[] Locations - { - get - { - if (locations == null) - { - locations = new DiagnosticResultLocation[] { }; - } - return locations; - } - - set - { - locations = value; - } - } - - public DiagnosticSeverity Severity { get; set; } - - public string Id { get; set; } - - public string Message { get; set; } - - public string Path - { - get - { - return Locations.Length > 0 ? Locations[0].Path : ""; - } - } - - public int Line - { - get - { - return Locations.Length > 0 ? Locations[0].Line : -1; - } - } - - public int Column - { - get - { - return Locations.Length > 0 ? Locations[0].Column : -1; - } - } - } -} \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/Verifiers/DiagnosticVerifier.cs b/test/Common/CodeCracker.Test.Common/Verifiers/DiagnosticVerifier.cs index 6163123c2..d692a8e10 100644 --- a/test/Common/CodeCracker.Test.Common/Verifiers/DiagnosticVerifier.cs +++ b/test/Common/CodeCracker.Test.Common/Verifiers/DiagnosticVerifier.cs @@ -1,6 +1,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using System.Collections.Generic; using System.Linq; using System.Text; @@ -113,7 +114,8 @@ protected async Task VerifyBasicDiagnosticAsync(string[] sources, DiagnosticResu private async static Task VerifyDiagnosticsAsync(string[] sources, string language, DiagnosticAnalyzer analyzer, DiagnosticResult[] expected, LanguageVersion languageVersionCSharp, Microsoft.CodeAnalysis.VisualBasic.LanguageVersion languageVersionVB) { var diagnostics = await GetSortedDiagnosticsAsync(sources, language, analyzer, languageVersionCSharp, languageVersionVB).ConfigureAwait(true); - VerifyDiagnosticResults(diagnostics, analyzer, expected); + var defaultFilePath = language == LanguageNames.CSharp ? CSharpDefaultFilePath : VisualBasicDefaultFilePath; + VerifyDiagnosticResults(diagnostics, analyzer, defaultFilePath, expected); } @@ -124,7 +126,7 @@ private async static Task VerifyDiagnosticsAsync(string[] sources, string langua /// The Diagnostics found by the compiler after running the analyzer on the source code /// The analyzer that was being run on the sources /// Diagnsotic Results that should have appeared in the code - private static void VerifyDiagnosticResults(IEnumerable actualResults, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expectedResults) + private static void VerifyDiagnosticResults(IEnumerable actualResults, DiagnosticAnalyzer analyzer, string defaultFilePath, params DiagnosticResult[] expectedResults) { var expectedCount = expectedResults.Length; var actualCount = actualResults.Count(); @@ -139,9 +141,9 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult for (int i = 0; i < expectedResults.Length; i++) { var actual = actualResults.ElementAt(i); - var expected = expectedResults[i]; + var expected = expectedResults[i].WithDefaultPath(defaultFilePath); - if (expected.Line == -1 && expected.Column == -1) + if (!expected.HasLocation) { if (actual.Location != Location.None) { @@ -150,17 +152,17 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult } else { - VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Locations.First()); + VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Spans.First()); var additionalLocations = actual.AdditionalLocations.ToArray(); - if (additionalLocations.Length != expected.Locations.Length - 1) + if (additionalLocations.Length != expected.Spans.Length - 1) { - Assert.True(false, $"Expected {expected.Locations.Length - 1} additional locations but got {additionalLocations.Length} for Diagnostic:\r\n {FormatDiagnostics(analyzer, actual)}\r\n"); + Assert.True(false, $"Expected {expected.Spans.Length - 1} additional locations but got {additionalLocations.Length} for Diagnostic:\r\n {FormatDiagnostics(analyzer, actual)}\r\n"); } for (int j = 0; j < additionalLocations.Length; ++j) { - VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Locations[j + 1]); + VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Spans[j + 1]); } } @@ -182,7 +184,7 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult /// The diagnostic that was found in the code /// The Location of the Diagnostic found in the code /// The DiagnosticResultLocation that should have been found - private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, Location actual, DiagnosticResultLocation expected) + private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, Location actual, FileLinePositionSpan expected) { var actualSpan = actual.GetLineSpan(); @@ -193,13 +195,13 @@ private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagno // Only check line position if there is an actual line in the real diagnostic if (actualLinePosition.Line > 0) - if (actualLinePosition.Line + 1 != expected.Line) - Assert.True(false, $"Expected diagnostic to be on line \"{expected.Line}\" was actually on line \"{actualLinePosition.Line + 1}\"\r\n\r\nDiagnostic:\r\n {FormatDiagnostics(analyzer, diagnostic)}\r\n"); + if (actualLinePosition.Line != expected.StartLinePosition.Line) + Assert.True(false, $"Expected diagnostic to be on line \"{expected.StartLinePosition.Line + 1}\" was actually on line \"{actualLinePosition.Line + 1}\"\r\n\r\nDiagnostic:\r\n {FormatDiagnostics(analyzer, diagnostic)}\r\n"); // Only check column position if there is an actual column position in the real diagnostic if (actualLinePosition.Character > 0) - if (actualLinePosition.Character + 1 != expected.Column) - Assert.True(false, $"Expected diagnostic to start at column \"{expected.Column}\" was actually at column \"{actualLinePosition.Character + 1}\"\r\n\r\nDiagnostic:\r\n {FormatDiagnostics(analyzer, diagnostic)}\r\n"); + if (actualLinePosition.Character != expected.StartLinePosition.Character) + Assert.True(false, $"Expected diagnostic to start at column \"{expected.StartLinePosition.Character + 1}\" was actually at column \"{actualLinePosition.Character + 1}\"\r\n\r\nDiagnostic:\r\n {FormatDiagnostics(analyzer, diagnostic)}\r\n"); } /// diff --git a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj index e27355417..7f18764a2 100644 --- a/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj +++ b/test/VisualBasic/CodeCracker.Test/CodeCracker.Test.vbproj @@ -60,7 +60,7 @@ - + diff --git a/test/VisualBasic/CodeCracker.Test/Design/NameOfTests.vb b/test/VisualBasic/CodeCracker.Test/Design/NameOfTests.vb index 641b65c8e..f5b70fa98 100644 --- a/test/VisualBasic/CodeCracker.Test/Design/NameOfTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Design/NameOfTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Design +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Design @@ -591,13 +592,9 @@ End Class" End Function Private Function CreateNameofDiagnosticResult(nameofArgument As String, diagnosticLine As Integer, diagnosticColumn As Integer, Optional id As DiagnosticId = DiagnosticId.NameOf) As DiagnosticResult - Return New DiagnosticResult With - { - .Id = id.ToDiagnosticId(), - .Message = $"Use 'NameOf({nameofArgument})' instead of specifying the program element name.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", diagnosticLine, diagnosticColumn)} - } + Return New DiagnosticResult(id.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(diagnosticLine, diagnosticColumn) _ + .WithMessage($"Use 'NameOf({nameofArgument})' instead of specifying the program element name.") End Function End Class End Namespace \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/Design/StaticConstructorExceptionTests.vb b/test/VisualBasic/CodeCracker.Test/Design/StaticConstructorExceptionTests.vb index 9501ea066..de4131a19 100644 --- a/test/VisualBasic/CodeCracker.Test/Design/StaticConstructorExceptionTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Design/StaticConstructorExceptionTests.vb @@ -1,5 +1,6 @@ Imports CodeCracker.VisualBasic.Design Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Testing Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports System.IO @@ -18,12 +19,9 @@ Public Class TestClass End Sub End Class" - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.StaticConstructorException.ToDiagnosticId(), - .Message = "Don't throw exceptions inside static constructors.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 4, 9)} - } + Dim expected = New DiagnosticResult(DiagnosticId.StaticConstructorException.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(4, 9) _ + .WithMessage("Don't throw exceptions inside static constructors.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.vb b/test/VisualBasic/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.vb index b1f8d1987..aca8cb0da 100644 --- a/test/VisualBasic/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.vb @@ -1,5 +1,6 @@ Imports CodeCracker.VisualBasic.Performance Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Performance @@ -39,39 +40,27 @@ Namespace Performance Public Async Function CreateDiagnosticsWhenAssigningAPotentialConstant() As Task Dim test = "Dim a As Integer = 10".WrapInVBMethod() - Dim expected = New DiagnosticResult With - { - .Id = MakeLocalVariableConstWhenPossibleAnalyzer.Id, - .Message = "This variable can be made const.", - .Severity = DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 13)} - } + Dim expected = New DiagnosticResult(MakeLocalVariableConstWhenPossibleAnalyzer.Id, DiagnosticSeverity.Info) _ + .WithLocation(6, 13) _ + .WithMessage("This variable can be made const.") Await VerifyBasicDiagnosticAsync(test, expected) End Function Public Async Function CreateDiagnosticsWhenAssigningAPotentialConstantUsingTypeInference() As Task Dim test = "Dim a = 10".WrapInVBMethod() - Dim expected = New DiagnosticResult With - { - .Id = MakeLocalVariableConstWhenPossibleAnalyzer.Id, - .Message = "This variable can be made const.", - .Severity = DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 13)} - } + Dim expected = New DiagnosticResult(MakeLocalVariableConstWhenPossibleAnalyzer.Id, DiagnosticSeverity.Info) _ + .WithLocation(6, 13) _ + .WithMessage("This variable can be made const.") Await VerifyBasicDiagnosticAsync(test, expected) End Function Public Async Function CreateDiagnosticsWhenAssigningNothingToAReferenceType() As Task Dim test = "Dim a As Foo = Nothing".WrapInVBMethod() - Dim expected = New DiagnosticResult With - { - .Id = MakeLocalVariableConstWhenPossibleAnalyzer.Id, - .Message = "This variable can be made const.", - .Severity = DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 13)} - } + Dim expected = New DiagnosticResult(MakeLocalVariableConstWhenPossibleAnalyzer.Id, DiagnosticSeverity.Info) _ + .WithLocation(6, 13) _ + .WithMessage("This variable can be made const.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.vb b/test/VisualBasic/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.vb index ce396c0d5..e4176f42e 100644 --- a/test/VisualBasic/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Performance +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Performance @@ -26,13 +27,9 @@ Namespace Sample End Class End Namespace" - Dim expected = New DiagnosticResult With - { - .Id = RemoveWhereWhenItIsPossibleAnalyzer.Id, - .Message = "You can remove 'Where' moving the predicate to '" + method + "'.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 7, 23)} - } + Dim expected = New DiagnosticResult(RemoveWhereWhenItIsPossibleAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(7, 23) _ + .WithMessage("You can remove 'Where' moving the predicate to '" + method + "'.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Performance/SealedAttributeTests.vb b/test/VisualBasic/CodeCracker.Test/Performance/SealedAttributeTests.vb index ec0f627bb..23c231e93 100644 --- a/test/VisualBasic/CodeCracker.Test/Performance/SealedAttributeTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Performance/SealedAttributeTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Performance +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Performance @@ -12,13 +13,9 @@ Public Class MyAttribute Inherits System.Attribute End Class" - Dim expected = New DiagnosticResult With - { - .Id = SealedAttributeAnalyzer.Id, - .Message = "Mark 'MyAttribute' as NotInheritable.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 2, 14)} - } + Dim expected = New DiagnosticResult(SealedAttributeAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(2, 14) _ + .WithMessage("Mark 'MyAttribute' as NotInheritable.") Await VerifyBasicDiagnosticAsync(test, expected) @@ -35,13 +32,9 @@ Public Class OtherAttribute Inherits MyAttribute End Class" - Dim expected = New DiagnosticResult With - { - .Id = SealedAttributeAnalyzer.Id, - .Message = "Mark 'OtherAttribute' as NotInheritable.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 14)} - } + Dim expected = New DiagnosticResult(SealedAttributeAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(6, 14) _ + .WithMessage("Mark 'OtherAttribute' as NotInheritable.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Performance/StringBuilderInLoopTests.vb b/test/VisualBasic/CodeCracker.Test/Performance/StringBuilderInLoopTests.vb index 02db187a8..01d6f79a7 100644 --- a/test/VisualBasic/CodeCracker.Test/Performance/StringBuilderInLoopTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Performance/StringBuilderInLoopTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Performance +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Performance @@ -75,19 +76,16 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As DiagnosticResult = GetExpected() - expected.Locations(0).Line = 7 - expected.Locations(0).Column = 17 + Dim expected = New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(7, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a")) Await VerifyBasicDiagnosticAsync(source, expected) End Function Private Shared Function GetExpected() As DiagnosticResult - Return New DiagnosticResult With { - .Id = StringBuilderInLoopAnalyzer.Id, - .Message = String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 9, 17)} - } + Return New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(9, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a")) End Function @@ -116,9 +114,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As DiagnosticResult = GetExpected() - expected.Locations(0).Line = 7 - expected.Locations(0).Column = 17 + Dim expected = New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(7, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -134,19 +132,12 @@ End Namespace" Console.WriteLine(myString2) ".WrapInVBMethod() - Dim expected1 As New DiagnosticResult With { - .Id = StringBuilderInLoopAnalyzer.Id, - .Message = String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 10, 17)} - } - - Dim expected2 As New DiagnosticResult With { - .Id = StringBuilderInLoopAnalyzer.Id, - .Message = String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString2"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 11, 17)} - } + Dim expected1 = New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(10, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a")) + Dim expected2 = New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(11, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "myString2")) Await VerifyBasicDiagnosticAsync(source, expected1, expected2) End Function @@ -392,13 +383,9 @@ End Namespace" a += """" Next".WrapInVBMethod - Dim expected As New DiagnosticResult With - { - .Id = StringBuilderInLoopAnalyzer.Id, - .Message = String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 9, 17)} - } + Dim expected = New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(9, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -430,13 +417,9 @@ End Namespace" Loop Until DateTime.Now.Second Mod 2 = 0 ".WrapInVBMethod - Dim expected As New DiagnosticResult With - { - .Id = StringBuilderInLoopAnalyzer.Id, - .Message = String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 9, 17)} - } + Dim expected = New DiagnosticResult(StringBuilderInLoopAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(9, 17) _ + .WithMessage(String.Format(StringBuilderInLoopAnalyzer.MessageFormat, "a")) Await VerifyBasicDiagnosticAsync(source, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.vb b/test/VisualBasic/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.vb index c4ad336f1..2d65a860e 100644 --- a/test/VisualBasic/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Refactoring/AllowMembersOrderingAnalyzerTests.vb @@ -1,6 +1,7 @@ Imports Microsoft.CodeAnalysis.Diagnostics Imports CodeCracker.VisualBasic.Refactoring Imports Xunit +Imports Microsoft.CodeAnalysis.Testing Namespace Refactoring Public Class AllowMembersOrderingAnalyzerTests @@ -43,12 +44,9 @@ End {0}", typeDeclaration) End Sub End {0}", typeDeclaration) - Dim expected = New DiagnosticResult With { - .Id = AllowMembersOrderingAnalyzer.Id, - .Message = AllowMembersOrderingAnalyzer.MessageFormat, - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Hidden, - .Locations = {New DiagnosticResultLocation("Test0.vb", 2, 14 + typeDeclaration.Length)} - } + Dim expected = New DiagnosticResult(AllowMembersOrderingAnalyzer.Id, Microsoft.CodeAnalysis.DiagnosticSeverity.Hidden) _ + .WithLocation(2, 14 + typeDeclaration.Length) _ + .WithMessage(AllowMembersOrderingAnalyzer.MessageFormat) Await VerifyBasicDiagnosticAsync(test, expected) End Function End Class diff --git a/test/VisualBasic/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.vb b/test/VisualBasic/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.vb index feb3b99d3..64856acaf 100644 --- a/test/VisualBasic/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Refactoring/ChangeAnyToAllTests.vb @@ -1,5 +1,6 @@ Imports CodeCracker.VisualBasic.Refactoring Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Testing Imports System.Threading.Tasks Imports Xunit @@ -29,12 +30,9 @@ Namespace Refactoring Public Async Function AnyAndAllWithLinqCreatesDiagnostic(code As String, column As Integer, diagnosticId As DiagnosticId) As Task Dim source = code.WrapInVBMethod(imports:=" Imports System.Linq") - Dim expected = New DiagnosticResult With { - .Id = diagnosticId.ToDiagnosticId(), - .Message = If(diagnosticId = DiagnosticId.ChangeAnyToAll, ChangeAnyToAllAnalyzer.MessageAny, ChangeAnyToAllAnalyzer.MessageAll), - .Severity = DiagnosticSeverity.Hidden, - .Locations = {New DiagnosticResultLocation("Test0.vb", 9, column)} - } + Dim expected = New DiagnosticResult(diagnosticId.ToDiagnosticId(), DiagnosticSeverity.Hidden) _ + .WithLocation(9, column) _ + .WithMessage(If(diagnosticId = DiagnosticId.ChangeAnyToAll, ChangeAnyToAllAnalyzer.MessageAny, ChangeAnyToAllAnalyzer.MessageAll)) Await VerifyBasicDiagnosticAsync(source, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.vb b/test/VisualBasic/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.vb index f98bc3847..7c03192f9 100644 --- a/test/VisualBasic/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Reliability +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Reliability @@ -14,12 +15,9 @@ Namespace Reliability Public Async Function WhenAwaitingTaskAnalyzerCreatesDiagnostic(sample As String, column As Integer) As Task Dim test = sample.WrapInVBMethod(isAsync:=True) - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.UseConfigureAwaitFalse.ToDiagnosticId(), - .Message = "Consider using ConfigureAwait(False) on the awaited task.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Hidden, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, column)} - } + Dim expected = New DiagnosticResult(DiagnosticId.UseConfigureAwaitFalse.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Hidden) _ + .WithLocation(6, column) _ + .WithMessage("Consider using ConfigureAwait(False) on the awaited task.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Style/InterfaceNameTests.vb b/test/VisualBasic/CodeCracker.Test/Style/InterfaceNameTests.vb index 28adafc53..0c61b24b8 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/InterfaceNameTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/InterfaceNameTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Style +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Style @@ -23,12 +24,9 @@ End Namespace" End Interface End Namespace" - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.InterfaceName.ToDiagnosticId(), - .Message = InterfaceNameAnalyzer.MessageFormat, - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 2, 5)} - } + Dim expected = New DiagnosticResult(DiagnosticId.InterfaceName.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(2, 5) _ + .WithMessage(InterfaceNameAnalyzer.MessageFormat) Await VerifyBasicDiagnosticAsync(source, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb index 4e1c8a3a2..0a956c38a 100644 --- a/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Style/TernaryOperatorTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Style +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Style @@ -144,12 +145,9 @@ End Namespace" Public Async Function WhenUsingIfAndElseWithDirectReturnAnalyzerCreatesDiagnostic() As Task - Dim expected As New DiagnosticResult With { - .Id = DiagnosticId.TernaryOperator_Assignment.ToDiagnosticId(), - .Message = "You can use a ternary operator.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 8, 13)} - } + Dim expected = New DiagnosticResult(DiagnosticId.TernaryOperator_Assignment.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(8, 13) _ + .WithMessage("You can use a ternary operator.") Await VerifyBasicDiagnosticAsync(sourceAssign, expected) End Function @@ -793,12 +791,9 @@ End Namespace" Public Async Function WhenUsingIfAndElseWithDirectReturnAnalyzerCreatesDiagnostic() As Task - Dim expected As New DiagnosticResult With { - .Id = DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), - .Message = "You can use a ternary operator.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 13)} - } + Dim expected = New DiagnosticResult(DiagnosticId.TernaryOperator_Return.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(6, 13) _ + .WithMessage("You can use a ternary operator.") Await VerifyBasicDiagnosticAsync(sourceReturn, expected) End Function @@ -1005,12 +1000,9 @@ Class MyType End Function End Class" - Dim expected As New DiagnosticResult With { - .Id = DiagnosticId.TernaryOperator_Iif.ToDiagnosticId(), - .Message = "You can use a ternary operator.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 16)} - } + Dim expected = New DiagnosticResult(DiagnosticId.TernaryOperator_Iif.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(5, 16) _ + .WithMessage("You can use a ternary operator.") Await VerifyBasicDiagnosticAsync(source, expected) Await VerifyBasicFixAsync(source, fix) diff --git a/test/VisualBasic/CodeCracker.Test/Usage/ArgumentExceptionTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/ArgumentExceptionTests.vb index 681fe9584..b2ac9db8d 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/ArgumentExceptionTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/ArgumentExceptionTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Usage +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -24,12 +25,9 @@ Public Async Function Foo(a As Integer, b As Integer) As Task End Function ") - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.ArgumentException.ToDiagnosticId(), - .Message = "Type argument 'c' is not in the argument list.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 8, 44)} - } + Dim expected = New DiagnosticResult(DiagnosticId.ArgumentException.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(8, 44) _ + .WithMessage("Type argument 'c' is not in the argument list.") Await VerifyBasicDiagnosticAsync(test, expected) End Function @@ -42,12 +40,9 @@ Public Sub New(a As Integer, b As Integer) End Sub ") - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.ArgumentException.ToDiagnosticId(), - .Message = "Type argument 'c' is not in the argument list.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 8, 44)} - } + Dim expected = New DiagnosticResult(DiagnosticId.ArgumentException.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(8, 44) _ + .WithMessage("Type argument 'c' is not in the argument list.") Await VerifyBasicDiagnosticAsync(test, expected) End Function @@ -147,12 +142,9 @@ End Sub End Set End Property ") - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.ArgumentException.ToDiagnosticId(), - .Message = "Type argument 'paramName' is not in the argument list.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 11, 56)} - } + Dim expected = New DiagnosticResult(DiagnosticId.ArgumentException.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(11, 56) _ + .WithMessage("Type argument 'paramName' is not in the argument list.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.vb index ad742040d..f1f583c6d 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/DisposableFieldNotDisposedTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Usage +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -35,13 +36,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(5, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -83,20 +80,12 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 17)} - } - Dim expected2 As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field2"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(5, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) + Dim expected2 = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(6, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field2")) Await VerifyBasicDiagnosticAsync(source, expected, expected2) End Function @@ -122,13 +111,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(5, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -154,13 +139,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(6, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -208,13 +189,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 7, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(7, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -240,13 +217,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 8, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(8, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -273,13 +246,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(6, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -307,13 +276,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 6, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(6, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -334,13 +299,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Created.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(5, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function @@ -361,13 +322,9 @@ Namespace ConsoleApplication1 End Class End Namespace" - Dim expected As New DiagnosticResult With - { - .Id = DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), - .Message = String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field"), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Info, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 17)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposableFieldNotDisposed_Returned.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Info) _ + .WithLocation(5, 17) _ + .WithMessage(String.Format(DisposableFieldNotDisposedAnalyzer.MessageFormat, "field")) Await VerifyBasicDiagnosticAsync(source, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.vb index ecdd57888..89ea62f97 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/DisposablesShouldCallSuppressFinalizeTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Usage +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -15,12 +16,9 @@ Public Class MyType End Sub End Class " - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), - .Message = "'MyType' should call GC.SuppressFinalize inside the Dispose method.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 16)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(5, 16) _ + .WithMessage("'MyType' should call GC.SuppressFinalize inside the Dispose method.") Await VerifyBasicDiagnosticAsync(test, expected) End Function @@ -109,12 +107,9 @@ Public NotInheritable Class MyType End Class " - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), - .Message = "'MyType' should call GC.SuppressFinalize inside the Dispose method.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 5, 16)} - } + Dim expected = New DiagnosticResult(DiagnosticId.DisposablesShouldCallSuppressFinalize.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(5, 16) _ + .WithMessage("'MyType' should call GC.SuppressFinalize inside the Dispose method.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Usage/IPAddressAnalyzerTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/IPAddressAnalyzerTests.vb index c2c4a62cf..83b260e86 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/IPAddressAnalyzerTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/IPAddressAnalyzerTests.vb @@ -2,6 +2,7 @@ Imports CodeCracker.VisualBasic Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Public Class IPAddressAnalyzerTests @@ -53,11 +54,9 @@ End Namespace" End Function Private Function CreateDiagnosticResult(line As Integer, column As Integer, errorMessageAction As Action) As DiagnosticResult - Return New DiagnosticResult With { - .Id = DiagnosticId.IPAddress.ToDiagnosticId(), - .Message = GetErrorMessage(errorMessageAction), - .Severity = DiagnosticSeverity.Error, - .Locations = {New DiagnosticResultLocation("Test0.vb", line, column)}} + Return New DiagnosticResult(DiagnosticId.IPAddress.ToDiagnosticId(), DiagnosticSeverity.Error) _ + .WithLocation(line, column) _ + .WithMessage(GetErrorMessage(errorMessageAction)) End Function Private Shared Function GetErrorMessage(action As Action) As String diff --git a/test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb index a1b921ef7..6b573b250 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/JsonNetAnalyzerTests.vb @@ -1,5 +1,6 @@ Imports CodeCracker.VisualBasic.Usage Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -19,12 +20,9 @@ Namespace ConsoleApplication1 End Namespace" Private Shared Function CreateDiagnosticResult(line As Integer, column As Integer) As DiagnosticResult - Return New DiagnosticResult With { - .Id = DiagnosticId.JsonNet.ToDiagnosticId(), - .Message = "Unexpected end when reading JSON. Path '', line 1, position 3.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Error, - .Locations = {New DiagnosticResultLocation("Test0.vb", line, column)} - } + Return New DiagnosticResult(DiagnosticId.JsonNet.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Error) _ + .WithLocation(line, column) _ + .WithMessage("Unexpected end when reading JSON. Path '', line 1, position 3.") End Function Protected Overrides Function GetDiagnosticAnalyzer() As DiagnosticAnalyzer diff --git a/test/VisualBasic/CodeCracker.Test/Usage/MustInheritClassShouldNotHavePublicConstructorTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/MustInheritClassShouldNotHavePublicConstructorTests.vb index 30093ff9e..3ec7ccf1e 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/MustInheritClassShouldNotHavePublicConstructorTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/MustInheritClassShouldNotHavePublicConstructorTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Usage +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -14,12 +15,9 @@ MustInherit Class Foo End Sub End Class" - Dim expected = New DiagnosticResult With { - .Id = DiagnosticId.AbstractClassShouldNotHavePublicCtors.ToDiagnosticId(), - .Message = "Constructor should not be public.", - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", 3, 5)} - } + Dim expected = New DiagnosticResult(DiagnosticId.AbstractClassShouldNotHavePublicCtors.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(3, 5) _ + .WithMessage("Constructor should not be public.") Await VerifyBasicDiagnosticAsync(test, expected) End Function diff --git a/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb index e6c044c9c..1031f3a59 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/UnusedParametersTests.vb @@ -1,4 +1,5 @@ Imports CodeCracker.VisualBasic.Usage +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -704,12 +705,9 @@ End Class" End Function Private Function CreateDiagnosticResult(parameterName As String, line As Integer, column As Integer) As DiagnosticResult - Return New DiagnosticResult With { - .Id = DiagnosticId.UnusedParameters.ToDiagnosticId(), - .Message = String.Format(UnusedParametersAnalyzer.Message, parameterName), - .Severity = Microsoft.CodeAnalysis.DiagnosticSeverity.Warning, - .Locations = {New DiagnosticResultLocation("Test0.vb", line, column)} - } + Return New DiagnosticResult(DiagnosticId.UnusedParameters.ToDiagnosticId(), Microsoft.CodeAnalysis.DiagnosticSeverity.Warning) _ + .WithLocation(line, column) _ + .WithMessage(String.Format(UnusedParametersAnalyzer.Message, parameterName)) End Function End Class End Namespace \ No newline at end of file diff --git a/test/VisualBasic/CodeCracker.Test/Usage/UriAnalyzerTests.vb b/test/VisualBasic/CodeCracker.Test/Usage/UriAnalyzerTests.vb index 92978725d..bb54fcd57 100644 --- a/test/VisualBasic/CodeCracker.Test/Usage/UriAnalyzerTests.vb +++ b/test/VisualBasic/CodeCracker.Test/Usage/UriAnalyzerTests.vb @@ -1,6 +1,7 @@ Imports CodeCracker.VisualBasic.Usage Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Testing Imports Xunit Namespace Usage @@ -78,12 +79,9 @@ End Namespace" End Function Private Shared Function CreateDiagnosticResult(line As Integer, column As Integer, getErrorMessageAction As Action) As DiagnosticResult - Return New DiagnosticResult() With { - .Id = DiagnosticId.Uri.ToDiagnosticId(), - .Message = GetErrorMessage(getErrorMessageAction), - .Severity = DiagnosticSeverity.[Error], - .Locations = New DiagnosticResultLocation() {New DiagnosticResultLocation("Test0.vb", line, column)} - } + Return New DiagnosticResult(DiagnosticId.Uri.ToDiagnosticId(), DiagnosticSeverity.Error) _ + .WithLocation(line, column) _ + .WithMessage(GetErrorMessage(getErrorMessageAction)) End Function Private Shared Function GetErrorMessage(action As Action) As String From 9a6b8fe89672d2cc5f423d313a7eccc6d170e5d4 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 9 Sep 2018 23:55:08 -0500 Subject: [PATCH 205/234] Add verifier helpers for testing --- .../CSharpCodeFixVerifier`2+Test.cs | 33 +++++++++++++ .../CSharpCodeFixVerifier`2.cs | 49 +++++++++++++++++++ .../CodeCracker.Test.Common.csproj | 6 +++ .../CodeCracker.Test.Common/EmptyAnalyzer.cs | 17 +++++++ .../VisualBasicCodeFixVerifier`2+Test.cs | 33 +++++++++++++ .../VisualBasicCodeFixVerifier`2.cs | 49 +++++++++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2+Test.cs create mode 100644 test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2.cs create mode 100644 test/Common/CodeCracker.Test.Common/EmptyAnalyzer.cs create mode 100644 test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2+Test.cs create mode 100644 test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2.cs diff --git a/test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2+Test.cs b/test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2+Test.cs new file mode 100644 index 000000000..00993b8c5 --- /dev/null +++ b/test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2+Test.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace CodeCracker.Test +{ + public static partial class CSharpCodeFixVerifier + { + public class Test : CodeFixTest + { + public override string Language => LanguageNames.CSharp; + + protected override string DefaultFileExt => "cs"; + + protected override CompilationOptions CreateCompilationOptions() + => new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true); + + protected override IEnumerable GetDiagnosticAnalyzers() + { + yield return new TAnalyzer(); + } + + protected override IEnumerable GetCodeFixProviders() + { + yield return new TCodeFix(); + } + } + } +} diff --git a/test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2.cs b/test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2.cs new file mode 100644 index 000000000..7e64e1b0c --- /dev/null +++ b/test/Common/CodeCracker.Test.Common/CSharpCodeFixVerifier`2.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace CodeCracker.Test +{ + public static partial class CSharpCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public static DiagnosticResult Diagnostic() + => CSharpCodeFixVerifier.Diagnostic(); + + public static DiagnosticResult Diagnostic(string diagnosticId) + => CSharpCodeFixVerifier.Diagnostic(diagnosticId); + + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => new DiagnosticResult(descriptor); + + public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source }; + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + + public static Task VerifyCodeFixAsync(string source, string fixedSource) + => VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + public static Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) + => VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + public static Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) + { + var test = new Test + { + TestCode = source, + FixedCode = fixedSource, + }; + + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + } +} diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index db5e82f6f..ee17f57f6 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -45,6 +45,7 @@ + @@ -52,6 +53,9 @@ + + + @@ -59,6 +63,8 @@ + + \ No newline at end of file diff --git a/test/Common/CodeCracker.Test.Common/EmptyAnalyzer.cs b/test/Common/CodeCracker.Test.Common/EmptyAnalyzer.cs new file mode 100644 index 000000000..0d1f5200e --- /dev/null +++ b/test/Common/CodeCracker.Test.Common/EmptyAnalyzer.cs @@ -0,0 +1,17 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace CodeCracker.Test +{ + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public class EmptyAnalyzer : DiagnosticAnalyzer + { + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Empty; + + public override void Initialize(AnalysisContext context) + { + } + } +} diff --git a/test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2+Test.cs b/test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2+Test.cs new file mode 100644 index 000000000..f41652de3 --- /dev/null +++ b/test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2+Test.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic; + +namespace CodeCracker.Test +{ + public static partial class VisualBasicCodeFixVerifier + { + public class Test : CodeFixTest + { + public override string Language => LanguageNames.VisualBasic; + + protected override string DefaultFileExt => "vb"; + + protected override CompilationOptions CreateCompilationOptions() + => new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + + protected override IEnumerable GetDiagnosticAnalyzers() + { + yield return new TAnalyzer(); + } + + protected override IEnumerable GetCodeFixProviders() + { + yield return new TCodeFix(); + } + } + } +} diff --git a/test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2.cs b/test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2.cs new file mode 100644 index 000000000..76964fad3 --- /dev/null +++ b/test/Common/CodeCracker.Test.Common/VisualBasicCodeFixVerifier`2.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace CodeCracker.Test +{ + public static partial class VisualBasicCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public static DiagnosticResult Diagnostic() + => VisualBasicCodeFixVerifier.Diagnostic(); + + public static DiagnosticResult Diagnostic(string diagnosticId) + => VisualBasicCodeFixVerifier.Diagnostic(diagnosticId); + + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => new DiagnosticResult(descriptor); + + public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source }; + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + + public static Task VerifyCodeFixAsync(string source, string fixedSource) + => VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + public static Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) + => VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + public static Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) + { + var test = new Test + { + TestCode = source, + FixedCode = fixedSource, + }; + + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + } +} From 415d5e9409e2ef5b0e383824f33ec3cf9c0698e0 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 10 Sep 2018 00:34:29 -0500 Subject: [PATCH 206/234] Convert CatchEmptyTests to the new test library --- .../Design/CatchEmptyTests.cs | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Design/CatchEmptyTests.cs b/test/CSharp/CodeCracker.Test/Design/CatchEmptyTests.cs index 7dd1728bc..cd1582067 100644 --- a/test/CSharp/CodeCracker.Test/Design/CatchEmptyTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/CatchEmptyTests.cs @@ -1,12 +1,13 @@ -using CodeCracker.CSharp.Design; -using System.Threading.Tasks; +using System.Threading.Tasks; +using CodeCracker.CSharp.Design; using Xunit; namespace CodeCracker.Test.CSharp.Design { - public class CatchEmptyTests : CodeFixVerifier - { + using Verify = CSharpCodeFixVerifier; + public class CatchEmptyTests + { [Fact] public async Task CatchEmptyAnalyserCreateDiagnostic() { @@ -17,7 +18,7 @@ namespace ConsoleApplication1 { class TypeName { - public async Task Foo() + public async {|CS0246:Task|} {|CS0161:{|CS1983:Foo|}|}() { try { @@ -31,7 +32,7 @@ public async Task Foo() } }"; - await VerifyCSharpHasNoDiagnosticsAsync(source); + await Verify.VerifyAnalyzerAsync(source); } [Fact] @@ -44,7 +45,7 @@ namespace ConsoleApplication1 { class TypeName { - public async Task Foo() + public async {|CS0246:Task|} {|CS0161:{|CS1983:Foo|}|}() { try { @@ -57,7 +58,7 @@ public async Task Foo() } } }"; - await VerifyCSharpHasNoDiagnosticsAsync(source); + await Verify.VerifyAnalyzerAsync(source); } [Fact] @@ -87,7 +88,7 @@ public void Foo() } } }"; - await VerifyCSharpHasNoDiagnosticsAsync(source); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async Task NotAllowedToReturnOutOfEmtpyCatchBlock() @@ -106,13 +107,13 @@ public void Foo() { // do something } - catch + [|catch { if (x == 1) throw; else return; - } + }|] } } }"; @@ -129,19 +130,19 @@ public void Foo() { try { - // do something - } - catch (Exception ex) - { - if (x == 1) - throw; - else - return; + // do something } + catch (Exception ex) + { + if (x == 1) + throw; + else + return; } } + } }"; - await VerifyCSharpFixAsync(test, fixtest, 0, allowNewCompilerDiagnostics: true); + await Verify.VerifyCodeFixAsync(test, fixtest); } [Fact] public async Task WhenFindCatchEmptyThenPutExceptionClass() @@ -159,10 +160,10 @@ public void Foo() { // do something } - catch + [|catch { int x = 0; - } + }|] } } }"; @@ -180,14 +181,14 @@ public void Foo() { // do something } - catch (Exception ex) - { - int x = 0; - } + catch (Exception ex) + { + int x = 0; } } + } }"; - await VerifyCSharpFixAsync(test, fixtest, 0, allowNewCompilerDiagnostics: true); + await Verify.VerifyCodeFixAsync(test, fixtest); } [Fact] public async Task AddCatchEvenIfThereIsReturnInBlock() @@ -205,11 +206,11 @@ public void Foo() { // do something } - catch + [|catch { int x = 0; return; - } + }|] } } }"; @@ -227,15 +228,15 @@ public void Foo() { // do something } - catch (Exception ex) - { - int x = 0; - return; - } + catch (Exception ex) + { + int x = 0; + return; } } + } }"; - await VerifyCSharpFixAsync(test, fixtest, 0, allowNewCompilerDiagnostics: true); + await Verify.VerifyCodeFixAsync(test, fixtest); } } } \ No newline at end of file From b50066614aa98a8813d3f79594469c6581a457c9 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 10 Sep 2018 00:50:01 -0500 Subject: [PATCH 207/234] Convert EmptyCatchBlockTests to the new test library --- .../Design/EmptyCatchBlockTests.cs | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Design/EmptyCatchBlockTests.cs b/test/CSharp/CodeCracker.Test/Design/EmptyCatchBlockTests.cs index 0ecab7be1..87ea33784 100644 --- a/test/CSharp/CodeCracker.Test/Design/EmptyCatchBlockTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/EmptyCatchBlockTests.cs @@ -4,7 +4,9 @@ namespace CodeCracker.Test.CSharp.Design { - public class EmptyCatchBlockTests : CodeFixVerifier + using Verify = CSharpCodeFixVerifier; + + public class EmptyCatchBlockTests { readonly string test = @" using System; @@ -20,9 +22,9 @@ public async Task Foo() { // do something } - catch + [|catch { - } + }|] } } }"; @@ -36,7 +38,7 @@ namespace ConsoleApplication1 { class TypeName { - public async Task Foo() + public async {|CS0246:Task|} {|CS0161:{|CS1983:Foo|}|}() { try { @@ -49,7 +51,7 @@ public async Task Foo() } } }"; - await VerifyCSharpHasNoDiagnosticsAsync(test); + await Verify.VerifyAnalyzerAsync(test); } [Fact] @@ -72,7 +74,7 @@ public async Task Foo() } } }"; - await VerifyCSharpFixAsync(test, fixtest, 0, allowNewCompilerDiagnostics: false, formatBeforeCompare: true); + await Verify.VerifyCodeFixAsync(test, fixtest); } [Fact] @@ -88,15 +90,20 @@ class TypeName { public async Task Foo() { - { - // do something - } - //TODO: Consider reading MSDN Documentation about how to use Try...Catch => http://msdn.microsoft.com/en-us/library/0yd65esw.aspx + { + // do something } + //TODO: Consider reading MSDN Documentation about how to use Try...Catch => http://msdn.microsoft.com/en-us/library/0yd65esw.aspx + } } }"; - await VerifyCSharpFixAsync(test, fixtest, 1, allowNewCompilerDiagnostics: false, formatBeforeCompare: true); + await new Verify.Test + { + TestCode = test, + FixedCode = fixtest, + CodeFixIndex = 1, + }.RunAsync(); } [Fact] @@ -116,14 +123,19 @@ public async Task Foo() { // do something } - catch (Exception ex) - { - throw; - } + catch (Exception ex) + { + throw; } } + } }"; - await VerifyCSharpFixAsync(test, fixtest, 2, allowNewCompilerDiagnostics: true, formatBeforeCompare: true); + await new Verify.Test + { + TestCode = test, + FixedCode = fixtest, + CodeFixIndex = 2, + }.RunAsync(); } @@ -137,16 +149,16 @@ namespace ConsoleApplication1 { class TypeName { - public async Task Foo() + public async {|CS0246:Task|} {|CS0161:{|CS1983:Foo|}|}() { int x; try { // do something } - catch (System.ArgumentException ae) + [|catch (System.ArgumentException ae) { - } + }|] catch (System.Exception ex) { x = 1; @@ -162,7 +174,7 @@ namespace ConsoleApplication1 { class TypeName { - public async Task Foo() + public async {|CS0246:Task|} {|CS0161:{|CS1983:Foo|}|}() { int x; try @@ -176,7 +188,7 @@ public async Task Foo() } } }"; - await VerifyCSharpFixAsync(test, fixtest, 0); + await Verify.VerifyCodeFixAsync(test, fixtest); } } } \ No newline at end of file From eba2e8d68bbdf5e07167ff1fce35d4484668ac30 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 10 Sep 2018 01:02:38 -0500 Subject: [PATCH 208/234] Convert InconsistentAccessibilityTests to the new test library --- ...entAccessibilityTests.FieldPropertyType.cs | 25 ++++--- ...cessibilityTests.MethodIndexerParameter.cs | 71 +++++++++---------- ...essibilityTests.MethodIndexerReturnType.cs | 21 +++--- 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.FieldPropertyType.cs b/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.FieldPropertyType.cs index f90adea3e..b7d198c6d 100644 --- a/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.FieldPropertyType.cs +++ b/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.FieldPropertyType.cs @@ -1,16 +1,19 @@ using System.Threading.Tasks; +using CodeCracker.CSharp.Design.InconsistentAccessibility; using Xunit; namespace CodeCracker.Test.CSharp.Design { - public partial class InconsistentAccessibilityTests : CodeFixVerifier + using Verify = CSharpCodeFixVerifier; + + public partial class InconsistentAccessibilityTests { [Fact] public async Task ShouldFixInconsistentAccessibilityErrorInClassFieldTypeAsync() { const string testCode = @"public class Dependent { - public DependedUpon field; + public DependedUpon {|CS0052:field|}; } class DependedUpon @@ -25,7 +28,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -33,7 +36,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInClassFieldTypeWhenQua { const string testCode = @"public class Dependent { - internal Dependent.DependedUpon field; + internal Dependent.DependedUpon {|CS0052:field|}; class DependedUpon { @@ -49,7 +52,7 @@ internal class DependedUpon } }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -57,7 +60,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInStructFieldTypeAsync( { const string testCode = @"public struct Dependent { - public DependedUpon field, field1; + public DependedUpon {|CS0052:field|}, {|CS0052:field1|}; } class DependedUpon @@ -72,7 +75,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -80,7 +83,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInPropertyTypeAsync() { const string testCode = @"public class Dependent { - public DependedUpon Property + public DependedUpon {|CS0053:Property|} { get { return null; } set { } @@ -104,7 +107,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -112,7 +115,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInPropertyTypeWhenUsing { const string testCode = @"public class Dependent { - public DependedUpon Property + public DependedUpon {|CS0053:Property|} { get; set; @@ -136,7 +139,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } } } diff --git a/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerParameter.cs b/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerParameter.cs index 822d16141..34b11d5ef 100644 --- a/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerParameter.cs +++ b/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerParameter.cs @@ -1,11 +1,12 @@ -using CodeCracker.CSharp.Design.InconsistentAccessibility; -using Microsoft.CodeAnalysis.CodeFixes; -using System.Threading.Tasks; +using System.Threading.Tasks; +using CodeCracker.CSharp.Design.InconsistentAccessibility; using Xunit; namespace CodeCracker.Test.CSharp.Design { - public partial class InconsistentAccessibilityTests : CodeFixVerifier + using Verify = CSharpCodeFixVerifier; + + public partial class InconsistentAccessibilityTests { [Theory] [InlineData("class","internal")] @@ -17,11 +18,11 @@ public async Task ShouldChangeAccessibilityWhenErrorInConstructor(string type, s var sourceCode = @" public " + type + @" Dependent { - public Dependent(int a, DependendedUpon d, string b) + public {|CS0051:Dependent|}(int a, DependendedUpon d, string b) { } } -" + dependedUponModfifier + @" class DependendedUpon +" + dependedUponModfifier + (dependedUponModfifier.Length > 0 ? " " : "") + @"class DependendedUpon { }"; @@ -36,7 +37,7 @@ public class DependendedUpon { }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Theory] @@ -49,7 +50,7 @@ public class DependendedUpon [InlineData("protected", "internal /* comment */", "protected /* comment */")] [InlineData("protected", "private", "protected")] [InlineData("protected internal", "", "protected internal")] - [InlineData("protected internal", " protected ", " protected internal ")] + [InlineData("protected internal", " protected ", "protected internal")] [InlineData("protected internal", "internal", "protected internal")] [InlineData("internal protected", "private", "protected internal")] [InlineData("internal", "protected", "internal")] @@ -59,11 +60,11 @@ public async Task ShouldChangeAccessibilityWhenErrrorInMethod(string methodModif var sourceCode = @" public class Dependent { - " + methodModifier + @" void SomeMethod(DependendedUpon d) + " + methodModifier + @" void {|CS0051:SomeMethod|}(DependendedUpon d) { } - " + dependedUponModifier + @" class DependendedUpon + " + dependedUponModifier + (dependedUponModifier.Length > 0 ? " " : "") + @"class DependendedUpon { } }"; @@ -80,7 +81,7 @@ public class Dependent } }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Theory] @@ -91,9 +92,9 @@ public async Task ShouldChangeAccessibilityWhenErrorInInterface(string interface var sourceCode = @" " + interfaceAccessibilityModifier + @" interface Dependent { - void SomeMethod(DependendedUpon d); + void {|CS0051:SomeMethod|}(DependendedUpon d); } -" + dependedUponModifier + @" class DependendedUpon +" + dependedUponModifier + (dependedUponModifier.Length > 0 ? " " : "") + @"class DependendedUpon { }"; @@ -106,7 +107,7 @@ public async Task ShouldChangeAccessibilityWhenErrorInInterface(string interface { }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -115,7 +116,7 @@ public async Task ShouldChangeAccessibilityWhenQualifiedNameIsUsedForParameterTy const string sourceCode = @" public class Dependent { - public Dependent(Dependent.DependendedUpon d) + public {|CS0051:Dependent|}(Dependent.DependendedUpon d) { } @@ -136,7 +137,7 @@ public class DependendedUpon } }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -145,7 +146,7 @@ public async Task ShouldChangeAccessibilityWhenAliasQualifiedNameIsUsedForParame const string sourceCode = @" public class Dependent { - public Dependent(global::DependendedUpon d) + public {|CS0051:Dependent|}(global::DependendedUpon d) { } } @@ -164,7 +165,7 @@ public class DependendedUpon { }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -173,7 +174,7 @@ public async Task ShouldChangeAccessibilityWhenUsingDelegateAsParameter() const string sourceCode = @" public class Dependent { - public Dependent(DependedUpon d) + public {|CS0051:Dependent|}(DependedUpon d) { } } @@ -188,7 +189,7 @@ public Dependent(DependedUpon d) } public delegate void DependedUpon(int a);"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -197,7 +198,7 @@ public async Task ShouldChangeAccessibilityWhenUsingEnumAsParameter() const string sourceCode = @" public class Dependent { - public Dependent(DependedUpon d) + public {|CS0051:Dependent|}(DependedUpon d) { } } @@ -212,7 +213,7 @@ public Dependent(DependedUpon d) } public enum DependedUpon {}"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -221,7 +222,7 @@ public async Task ShouldChangeAccessibilityWhenUsingInterfaceAsParameter() const string sourceCode = @" public class Dependent { - public Dependent(DependedUpon d) + public {|CS0051:Dependent|}(DependedUpon d) { } } @@ -236,7 +237,7 @@ public Dependent(DependedUpon d) } public interface DependedUpon {}"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -245,7 +246,7 @@ public async Task ShouldChangeAccessibilityWhenUsingGenericClassAsParameter() const string sourceCode = @" public class Dependent { - public Dependent(DependedUpon d) + public {|CS0051:Dependent|}(DependedUpon d) { } } @@ -260,7 +261,7 @@ public Dependent(DependedUpon d) } public class DependedUpon {}"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -269,7 +270,7 @@ public async Task ShouldChangeAccessibilityToAllPartialDeclarationsAsync() const string sourceCode = @" public class Dependent { - public Dependent(DependedUpon d) + public {|CS0051:Dependent|}(DependedUpon d) { } } @@ -288,7 +289,7 @@ public partial class DependedUpon {} class SomeClass {} public partial class DependedUpon {}"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -296,7 +297,7 @@ public async Task ShouldChangeAccessibilityWhenErrorInIndexerParameterAsync() { const string sourceCode = @"public class Dependent { - public int this[int idx, DependedUpon dependedUpon] + public int {|CS0055:this|}[int idx, DependedUpon dependedUpon] { get { return 0; } set { } @@ -320,7 +321,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -328,7 +329,7 @@ public async Task ShouldChangeAccessibilityWhenErrorInIndexerParameterUsingQuali { const string sourceCode = @"public class Dependent { - public int this[int idx, Dependent.DependedUpon dependedUpon] + public int {|CS0055:this|}[int idx, Dependent.DependedUpon dependedUpon] { get { return 0; } set { } @@ -352,7 +353,7 @@ public class DependedUpon } }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -360,7 +361,7 @@ public async Task ShouldChangeAccessibilityWhenErrorInMoreThanOneIndexerParamete { const string sourceCode = @"public class Dependent { - public int this[int idx, Dependent.DependedUpon dependedUpon, DependedUpon2 dependedUpon2] + public int {|CS0055:{|CS0055:this|}|}[int idx, Dependent.DependedUpon dependedUpon, DependedUpon2 dependedUpon2] { get { return 0; } set { } @@ -392,9 +393,7 @@ public class DependedUpon2 { }"; - await VerifyCSharpFixAsync(sourceCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(sourceCode, fixedCode).ConfigureAwait(false); } - - protected override CodeFixProvider GetCodeFixProvider() => new InconsistentAccessibilityCodeFixProvider(); } } diff --git a/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerReturnType.cs b/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerReturnType.cs index e397c7a4f..7b5d324a2 100644 --- a/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerReturnType.cs +++ b/test/CSharp/CodeCracker.Test/Design/InconsistentAccessibilityTests.MethodIndexerReturnType.cs @@ -1,16 +1,19 @@ using System.Threading.Tasks; +using CodeCracker.CSharp.Design.InconsistentAccessibility; using Xunit; namespace CodeCracker.Test.CSharp.Design { - public partial class InconsistentAccessibilityTests : CodeFixVerifier + using Verify = CSharpCodeFixVerifier; + + public partial class InconsistentAccessibilityTests { [Fact] public async Task ShouldFixInconsistentAccessibilityErrorInMethodReturnTypeAsync() { const string testCode = @"public class Dependent { - public DependedUpon Method() + public DependedUpon {|CS0050:Method|}() { return null; } @@ -31,7 +34,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -39,7 +42,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInMethodReturnTypeWhenQ { const string testCode = @"public class Dependent { - public Dependent.DependedUpon Method() + public Dependent.DependedUpon {|CS0050:Method|}() { return null; } @@ -60,7 +63,7 @@ public class DependedUpon } }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -68,7 +71,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInIndexerReturnTypeAsyn { const string testCode = @"public class Dependent { - public DependedUpon this[int a] + public DependedUpon {|CS0054:this|}[int a] { get { return null; } set { } @@ -91,7 +94,7 @@ public class DependedUpon { }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } [Fact] @@ -99,7 +102,7 @@ public async Task ShouldFixInconsistentAccessibilityErrorInIndexerReturnTypeWhen { const string testCode = @"public class Dependent { - public Dependent.DependedUpon this[int a] + public Dependent.DependedUpon {|CS0054:this|}[int a] { get { return null; } set { } @@ -122,7 +125,7 @@ public class DependedUpon } }"; - await VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false); + await Verify.VerifyCodeFixAsync(testCode, fixedCode).ConfigureAwait(false); } } } From a6e63422ca8f0081af6896d6c7fad4055e61d4e9 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 10 Sep 2018 14:02:17 -0500 Subject: [PATCH 209/234] Unindent code in WrapInCSharpClass and WrapInCSharpMethod --- .../Design/MakeMethodStaticTests.cs | 2 +- ...ocalVariablesConstWhenItIsPossibleTests.cs | 6 +-- .../AddBracesToSwitchSectionsTests.cs | 6 +-- .../Refactoring/ComputeExpressionTests.cs | 2 +- .../Refactoring/NumericLiteralTests.cs | 2 +- .../Refactoring/SplitIntoNestedIfTests.cs | 2 +- .../UseConfigureAwaitFalseTests.cs | 12 +++--- .../Style/RemoveCommentedCodeTests.cs | 2 +- .../Style/StringFormatTests.cs | 4 +- ...ssaryToStringInStringConcatenationTests.cs | 2 +- .../Style/UseEmptyStringTest.cs | 4 +- .../Style/UseStringEmptyTests.cs | 4 +- .../DisposableVariableNotDisposedTests.cs | 8 ++-- .../Usage/RemoveRedundantElseClauseTests.cs | 4 +- ...implifyRedundantBooleanComparisonsTests.cs | 32 +++++++-------- .../Usage/StringFormatArgsTests.cs | 14 +++---- .../Helpers/Extensions.cs | 40 ++++++++++++------- 17 files changed, 78 insertions(+), 68 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs index 2d8829a4a..eb64ea7dc 100644 --- a/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs +++ b/test/CSharp/CodeCracker.Test/Design/MakeMethodStaticTests.cs @@ -102,7 +102,7 @@ public async Task WithDiagnostic(string code) { var source = code.WrapInCSharpClass(); var expected = new DiagnosticResult(DiagnosticId.MakeMethodStatic.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(8, 18) + .WithLocation(8, 14) .WithMessage(string.Format(MakeMethodStaticAnalyzer.MessageFormat, "Foo")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs index 61b2311b3..5ab66e579 100644 --- a/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/MakeLocalVariablesConstWhenItIsPossibleTests.cs @@ -66,7 +66,7 @@ public async Task CreateDiagnosticsWhenAssigningAPotentialConstant() { var test = @"int a = 10;".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage("This variable can be made const."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -77,7 +77,7 @@ public async Task CreateDiagnosticsWhenAssigningAPotentialConstantInAVarDeclarat var test = @"var a = 10;".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage("This variable can be made const."); await VerifyCSharpDiagnosticAsync(test, expected); } @@ -88,7 +88,7 @@ public async Task CreateDiagnosticsWhenAssigningNullToAReferenceType() var test = @"Foo a = null;".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.MakeLocalVariableConstWhenItIsPossible.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage("This variable can be made const."); await VerifyCSharpDiagnosticAsync(test, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs index 9f8dfb62c..086e7287f 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/AddBracesToSwitchSectionsTests.cs @@ -71,7 +71,7 @@ public async Task CreateDiagnosticWhenSingleSwitchSectionHasNoBraces() break; }"; var diagnostic = new DiagnosticResult(DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage("Add braces for each section in this switch"); await VerifyCSharpDiagnosticAsync(test.WrapInCSharpMethod(), diagnostic); } @@ -96,7 +96,7 @@ public async Task CreateDiagnosticWhenNotAllSwitchSectionsHaveBraces() } }"; var diagnostic = new DiagnosticResult(DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage("Add braces for each section in this switch"); await VerifyCSharpDiagnosticAsync(test.WrapInCSharpMethod(), diagnostic); } @@ -121,7 +121,7 @@ public async Task CreateDiagnosticWhenDefaultSectionsHasNoBraces() break; }"; var diagnostic = new DiagnosticResult(DiagnosticId.AddBracesToSwitchSections.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage("Add braces for each section in this switch"); await VerifyCSharpDiagnosticAsync(test.WrapInCSharpMethod(), diagnostic); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs index 64f244a6c..66f89503c 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/ComputeExpressionTests.cs @@ -40,7 +40,7 @@ public async Task BinaryExpressionWithLiteralOnLeftAndRightCreatesDiagnostic(str var source = original.WrapInCSharpMethod(); var expression = original.Substring(columnOffset, original.Length - columnOffset - columnRightTrim - 1); var expected = new DiagnosticResult(DiagnosticId.ComputeExpression.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 17 + columnOffset) + .WithLocation(10, 13 + columnOffset) .WithMessage(string.Format(ComputeExpressionAnalyzer.Message, expression)); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs index feae0f6f6..00949a8b8 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/NumericLiteralTests.cs @@ -81,7 +81,7 @@ void Foo() await VerifyCSharpFixAsync(source, fixtest); } - private static DiagnosticResult CreateDiagnosticResult(string literal, bool isDecimal, int row = 10, int col = 25) + private static DiagnosticResult CreateDiagnosticResult(string literal, bool isDecimal, int row = 10, int col = 21) { return new DiagnosticResult(DiagnosticId.NumericLiteral.ToDiagnosticId(), DiagnosticSeverity.Hidden) .WithLocation(row, col) diff --git a/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs b/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs index b99818c1c..41da694f2 100644 --- a/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs +++ b/test/CSharp/CodeCracker.Test/Refactoring/SplitIntoNestedIfTests.cs @@ -34,7 +34,7 @@ public async Task IfWithAndCreatesDiagnostic() { var source = "if (true && true) { }".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.SplitIntoNestedIf.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 21) + .WithLocation(10, 17) .WithMessage(string.Format(SplitIntoNestedIfAnalyzer.Message)); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs b/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs index c8e981b55..ef2e99a68 100644 --- a/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs +++ b/test/CSharp/CodeCracker.Test/Reliability/UseConfigureAwaitFalseTests.cs @@ -9,12 +9,12 @@ namespace CodeCracker.Test.CSharp.Reliability public class UseConfigureAwaitFalseTests : CodeFixVerifier { [Theory] - [InlineData("System.Threading.Tasks.Task t; await t;", 48)] - [InlineData("System.Threading.Tasks.Task t; await t.ContinueWith(_ => 42);", 48)] - [InlineData("await System.Threading.Tasks.Task.Delay(1000);", 17)] - [InlineData("await System.Threading.Tasks.Task.FromResult(0);", 17)] - [InlineData("await System.Threading.Tasks.Task.Run(() => {});", 17)] - [InlineData("Func f; await f();", 54)] + [InlineData("System.Threading.Tasks.Task t; await t;", 44)] + [InlineData("System.Threading.Tasks.Task t; await t.ContinueWith(_ => 42);", 44)] + [InlineData("await System.Threading.Tasks.Task.Delay(1000);", 13)] + [InlineData("await System.Threading.Tasks.Task.FromResult(0);", 13)] + [InlineData("await System.Threading.Tasks.Task.Run(() => {});", 13)] + [InlineData("Func f; await f();", 50)] public async Task WhenAwaitingTaskAnalyzerCreatesDiagnostic(string sample, int column) { var test = sample.WrapInCSharpMethod(isAsync: true); diff --git a/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs b/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs index eba8b1ad0..e287e5941 100644 --- a/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/RemoveCommentedCodeTests.cs @@ -27,7 +27,7 @@ public async Task CreateDiagnosticForSingleLineCommentedCode() { var test = @"// a = 10;".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.RemoveCommentedCode.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage(RemoveCommentedCodeAnalyzer.MessageFormat); await VerifyCSharpDiagnosticAsync(test, expected); diff --git a/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs b/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs index bab1ee836..fdd944a07 100644 --- a/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/StringFormatTests.cs @@ -631,10 +631,10 @@ public async Task NestedStringFormatCreatesDiagnostic() { var source = @"var foo = string.Format(""{0}"", string.Format(""{0}"", 1 ) );".WrapInCSharpMethod(); var expected1 = new DiagnosticResult(DiagnosticId.StringFormat.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 27) + .WithLocation(10, 23) .WithMessage(StringFormatAnalyzer.MessageFormat.ToString()); var expected2 = new DiagnosticResult(DiagnosticId.StringFormat.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 48) + .WithLocation(10, 44) .WithMessage(StringFormatAnalyzer.MessageFormat.ToString()); await VerifyCSharpDiagnosticAsync(source, expected1, expected2); } diff --git a/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs b/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs index 3f049ba98..75af07ac2 100644 --- a/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/UnnecessaryToStringInStringConcatenationTests.cs @@ -30,7 +30,7 @@ public async Task InstantiatingAnStringBuilderAndCallToStringInsideAStringConcat { var source = @"var foo = ""a"" + new System.Text.StringBuilder().ToString();".WrapInCSharpMethod(); - var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(10, 64); + var expected = CreateUnnecessaryToStringInStringConcatenationDiagnosticResult(10, 60); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Style/UseEmptyStringTest.cs b/test/CSharp/CodeCracker.Test/Style/UseEmptyStringTest.cs index 500739bbf..84eb26fdf 100644 --- a/test/CSharp/CodeCracker.Test/Style/UseEmptyStringTest.cs +++ b/test/CSharp/CodeCracker.Test/Style/UseEmptyStringTest.cs @@ -194,8 +194,8 @@ public async Task FixAllInSolutionChangeMethodToStringEmpty() public async Task TwoEmptyStringsGenerateTwoDiagnostics() { var test = "var s = string.Empty + string.Empty;".WrapInCSharpMethod(); - var expected1 = CreateEmptyStringDiagnosticResult(10, 25); - var expected2 = CreateEmptyStringDiagnosticResult(10, 40); + var expected1 = CreateEmptyStringDiagnosticResult(10, 21); + var expected2 = CreateEmptyStringDiagnosticResult(10, 36); await VerifyCSharpDiagnosticAsync(test, expected1, expected2); } diff --git a/test/CSharp/CodeCracker.Test/Style/UseStringEmptyTests.cs b/test/CSharp/CodeCracker.Test/Style/UseStringEmptyTests.cs index 9134c2bca..9e492b404 100644 --- a/test/CSharp/CodeCracker.Test/Style/UseStringEmptyTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/UseStringEmptyTests.cs @@ -187,10 +187,10 @@ public async Task TwoEmptyStringsGenerateTwoDiagnostics() { var test = @"var s = """" + """";".WrapInCSharpMethod(); var expected1 = new DiagnosticResult(DiagnosticId.UseStringEmpty.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 25) + .WithLocation(10, 21) .WithMessage("Use 'String.Empty' instead of \"\""); var expected2 = new DiagnosticResult(DiagnosticId.UseStringEmpty.ToDiagnosticId(), DiagnosticSeverity.Hidden) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage("Use 'String.Empty' instead of \"\""); await VerifyCSharpDiagnosticAsync(test, expected1, expected2); } diff --git a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs index daad3e39a..590f108de 100644 --- a/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/DisposableVariableNotDisposedTests.cs @@ -159,7 +159,7 @@ public async Task DisposableVariableCreatesDiagnostic() { var source = "new System.IO.MemoryStream();".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -176,7 +176,7 @@ public async Task DisposableVariableDeclaredWithAnotherVariableCreatesOnlyOneDia { var source = "System.IO.MemoryStream a, b = new System.IO.MemoryStream();".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 47) + .WithLocation(10, 43) .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -446,7 +446,7 @@ public async Task DisposableVariablePassedAsParamCreatesDiagnostic() { var source = "string.Format(\"\", new System.IO.MemoryStream());".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 35) + .WithLocation(10, 31) .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -457,7 +457,7 @@ public async Task DisposableVariableCallsIncorrectDisposeCreatesDiagnostic() var source = @"var m = new System.IO.MemoryStream(); m.Dispose(true);".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.DisposableVariableNotDisposed.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 25) + .WithLocation(10, 21) .WithMessage(string.Format(DisposableVariableNotDisposedAnalyzer.MessageFormat, "MemoryStream")); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs b/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs index 9849a0655..82a32d51a 100644 --- a/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/RemoveRedundantElseClauseTests.cs @@ -122,7 +122,7 @@ public async Task CreateDiagnosticsWhenEmptyElse() var test = @"if(1 == 2){ return 1; } else { }".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.RemoveRedundantElseClause.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 41) + .WithLocation(10, 37) .WithMessage("Remove redundant else"); await VerifyCSharpDiagnosticAsync(test, expected); @@ -134,7 +134,7 @@ public async Task CreateDiagnosticsWhenEmptyElseWithoutBlockOnIf() var test = @"if(1 == 2) return 1; else { }".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.RemoveRedundantElseClause.ToDiagnosticId(), DiagnosticSeverity.Info) - .WithLocation(10, 38) + .WithLocation(10, 34) .WithMessage("Remove redundant else"); await VerifyCSharpDiagnosticAsync(test, expected); diff --git a/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs b/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs index b1fa44b3f..e5fe06e4d 100644 --- a/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/SimplifyRedundantBooleanComparisonsTests.cs @@ -10,22 +10,22 @@ public class SimplifyRedundantBooleanComparisonsTests : CodeFixVerifier { [Theory] - [InlineData("if (foo == true) {}", 21)] - [InlineData("if (true == foo) {}", 21)] - [InlineData("var fee = (foo == true);", 28)] - [InlineData("var fee = (true == foo);", 28)] - [InlineData("if (foo == false) {}", 21)] - [InlineData("if (false == foo) {}", 21)] - [InlineData("var fee = (foo == false);", 28)] - [InlineData("var fee = (false == foo);", 28)] - [InlineData("if (foo != true) {}", 21)] - [InlineData("if (true != foo) {}", 21)] - [InlineData("var fee = (foo != true);", 28)] - [InlineData("var fee = (true != foo);", 28)] - [InlineData("if (foo != false) {}", 21)] - [InlineData("if (false != foo) {}", 21)] - [InlineData("var fee = (foo != false);", 28)] - [InlineData("var fee = (false != true);", 28)] + [InlineData("if (foo == true) {}", 17)] + [InlineData("if (true == foo) {}", 17)] + [InlineData("var fee = (foo == true);", 24)] + [InlineData("var fee = (true == foo);", 24)] + [InlineData("if (foo == false) {}", 17)] + [InlineData("if (false == foo) {}", 17)] + [InlineData("var fee = (foo == false);", 24)] + [InlineData("var fee = (false == foo);", 24)] + [InlineData("if (foo != true) {}", 17)] + [InlineData("if (true != foo) {}", 17)] + [InlineData("var fee = (foo != true);", 24)] + [InlineData("var fee = (true != foo);", 24)] + [InlineData("if (foo != false) {}", 17)] + [InlineData("if (false != foo) {}", 17)] + [InlineData("var fee = (foo != false);", 24)] + [InlineData("var fee = (false != true);", 24)] public async Task WhenComparingWithBoolAnalyzerCreatesDiagnostic(string sample, int column) { sample = "bool foo; " + sample; // add declaration of foo diff --git a/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs b/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs index b5ffbb6e9..ebd90f4c7 100644 --- a/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/StringFormatArgsTests.cs @@ -84,7 +84,7 @@ public async Task NoParametersCreatesError() { var source = @"var result = string.Format(""{0}"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -94,7 +94,7 @@ public async Task LessParametersCreatesError() { var source = @"var result = string.Format(""one {0} two {1}"", ""a"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -104,7 +104,7 @@ public async Task MoreArgumentsCreatesWarning() { var source = @"var result = string.Format(""one {0} two {1}"", ""a"", ""b"", ""c"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage(StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -135,7 +135,7 @@ public async Task TwoParametersReferencingSamePlaceholderCreatesWarning() { var source = @"var result = string.Format(""one {0} two {0}"", ""a"", ""b"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage(StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -179,7 +179,7 @@ public async Task InvalidArgumentReferenceCreatesError() { var source = @"var result = string.Format(""one {1}"", ""a"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -189,7 +189,7 @@ public async Task NonIntegerPlaceholderCreatesError() { var source = @"var result = string.Format(""one {notZero}"", ""a"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_InvalidArgs.ToDiagnosticId(), DiagnosticSeverity.Error) - .WithLocation(10, 30) + .WithLocation(10, 26) .WithMessage(StringFormatArgsAnalyzer.InvalidArgsReferenceMessage); await VerifyCSharpDiagnosticAsync(source, expected); } @@ -199,7 +199,7 @@ public async Task UnusedArgsCreatesWarning() { var source = @"string.Format(""{0}{1}{3}{5}"", ""a"", ""b"", ""c"", ""d"", ""e"", ""f"");".WrapInCSharpMethod(); var expected = new DiagnosticResult(DiagnosticId.StringFormatArgs_ExtraArgs.ToDiagnosticId(), DiagnosticSeverity.Warning) - .WithLocation(10, 17) + .WithLocation(10, 13) .WithMessage(StringFormatArgsAnalyzer.IncorrectNumberOfArgsMessage); await VerifyCSharpDiagnosticAsync(source, expected); } diff --git a/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs b/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs index 082843818..7b6e955ab 100644 --- a/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs +++ b/test/Common/CodeCracker.Test.Common/Helpers/Extensions.cs @@ -4,33 +4,43 @@ public static class Extensions { public static string WrapInCSharpClass(this string code, string typeName = "TypeName", string usings = "") { + if (!code.StartsWith("\r") || code.StartsWith("\n")) + { + code = " " + code; + } + return $@" - using System;{usings} +using System;{usings} - namespace ConsoleApplication1 +namespace ConsoleApplication1 +{{ + class {typeName} {{ - class {typeName} - {{ - {code} - }} - }}"; +{code} + }} +}}"; } public static string WrapInCSharpMethod(this string code, bool isAsync = false, string typeName = "TypeName", string usings = "") { + if (!code.StartsWith("\r") || code.StartsWith("\n")) + { + code = " " + code; + } + return $@" - using System;{usings} +using System;{usings} - namespace ConsoleApplication1 +namespace ConsoleApplication1 +{{ + class {typeName} {{ - class {typeName} + public {(isAsync ? "async " : "")}void Foo() {{ - public {(isAsync ? "async " : "")}void Foo() - {{ - {code} - }} +{code} }} - }}"; + }} +}}"; } public static string WrapInVBClass(this string code, From 0dc53ea33c9cc11daf5694bf290e9ddd10b25dae Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 1 Oct 2018 15:02:23 -0500 Subject: [PATCH 210/234] Fixed many spelling and grammar issues There were tons of spelling errors that I spotted in the code. Along with fixing these, I have provided grammatical fixes as well. --- README.md | 59 ++++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index c6e7048ee..bfb59721e 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ You can find this document in the following languages [![Brazilian Portuguese](https://img.shields.io/badge/language-brazilan%20portuguese-brightgreen.svg)](https://github.com/code-cracker/code-cracker/blob/master/README.pt.md) -This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this +This is a community project, free and open source. Everyone is invited to contribute, fork, share and use the code. No money shall be charged by this software, nor it will be. Ever. ## Features @@ -30,23 +30,23 @@ Code | Analyzer | Severity | Description -- | -- | -- | -- [CC0003](http://code-cracker.github.io/diagnostics/CC0003.html) | CatchEmptyAnalyzer | Warning | Catch statements with no Exception as an argument is not recommended. Consider adding an Exception class to the catch statement. [CC0004](http://code-cracker.github.io/diagnostics/CC0004.html) | EmptyCatchBlockAnalyzer | Warning | An empty catch block suppress all errors and shouldn’t be used. If the error is expected consider logging it or changing the control flow such that it is explicit. -[CC0016](http://code-cracker.github.io/diagnostics/CC0016.html) | CopyEventToVariableBeforeFireAnalyzer | Warning | Events should always be checked for null before being invoked. As in a multi-threading context it is possible for an event to be unsuscribed between the moment where it is checked to be non-null and the moment it is raised, the event must be copied to a temporary variable before the check. -[CC0021](http://code-cracker.github.io/diagnostics/CC0021.html) | NameOfAnalyzer | Warning | In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produce code that is easier to refactor. -[CC0024](http://code-cracker.github.io/diagnostics/CC0024.html) | StaticConstructorExceptionAnalyzer | Warning | Static constructor are called before the first time a class is used but the caller doesn’t control when exactly. Exception thrown in this context force callers to use ‘try’ block around any useage of the class and should be avoided. -[CC0031](http://code-cracker.github.io/diagnostics/CC0031.html) | UseInvokeMethodToFireEventAnalyzer | Warning | In C#6 a delegate can be invoked using the null-propagating operator (?.) and it’s invoke method to avoid throwing a NullReference exception when there is no method attached to the delegate. +[CC0016](http://code-cracker.github.io/diagnostics/CC0016.html) | CopyEventToVariableBeforeFireAnalyzer | Warning | Events should always be checked for null before being invoked. As in a multi-threading context, it is possible for an event to be unsubscribed between the moment where it is checked to be non-null and the moment it is raised, the event must be copied to a temporary variable before the check. +[CC0021](http://code-cracker.github.io/diagnostics/CC0021.html) | NameOfAnalyzer | Warning | In C#6 the nameof() operator should be used to specify the name of a program element instead of a string literal as it produces code that is easier to refactor. +[CC0024](http://code-cracker.github.io/diagnostics/CC0024.html) | StaticConstructorExceptionAnalyzer | Warning | Static constructor are called before the first time a class is used but the caller doesn’t control when exactly. Exceptions thrown in this context force callers to use ‘try’ block around any usage of the class and should be avoided. +[CC0031](http://code-cracker.github.io/diagnostics/CC0031.html) | UseInvokeMethodToFireEventAnalyzer | Warning | In C#6 a delegate can be invoked using the null-propagating operator (?.) and its invoke method to avoid throwing a NullReference exception when there is no method attached to the delegate. ## Installing -You may use CodeCracker in two ways: as an analyzer library that you install with Nuget into your project or as a Visual Studio extension. +You may use CodeCracker in two ways: as an analyzer library that you install with NuGet into your project, or as a Visual Studio extension. The way you want to use it depends on the scenario you are working on. You most likely want the Nuget package. If you want the analyzers to work during your build, and generate warnings and errors during the build, also on build servers, then you want -to use the Nuget package. The package is available on nuget ([C#](https://www.nuget.org/packages/codecracker.CSharp), +to use the Nuget package. The package is available on NuGet ([C#](https://www.nuget.org/packages/codecracker.CSharp), [VB](https://www.nuget.org/packages/codecracker.VisualBasic)). If you want to be able to configure which analyzers are being used in your project, and which ones you will ignore, and commit those changes to source control and share with your team, then you also want the Nuget package. -To install from Nuget, for the C# version: +To install from NuGet, for the C# version: ```powershell Install-Package CodeCracker.CSharp @@ -62,7 +62,7 @@ Or use the Package Manager in Visual Studio. There is also a version for both named `CodeCracker` only, but it makes no sense to get it, you should search for the C# or VB version. -If you want the alpha builds that build on each push to the repo, add https://www.myget.org/F/codecrackerbuild/ to your Nuget feed. +If you want the alpha builds that build on each push to the repo, add [this](https://www.myget.org/F/codecrackerbuild/) to your NuGet feed. We only push complete releases to Nuget.org, and commit builds go to Myget.org. If you want global analyzers that will work on every project you open in Visual Studio, then you want the Extension. @@ -92,13 +92,13 @@ The main supported IDE for development is Visual Studio 2017. We do not support VS 2015 anymore. Questions, comments, bug reports, and pull requests are all welcome. -Bug reports that include steps-to-reproduce (including code) are +Bug reports that include steps to reproduce (including code) are preferred. Even better, make them in the form of pull requests. Before you start to work on an existing issue, check if it is not assigned to anyone yet, and if it is, talk to that person. -Also check the project [board](https://huboard.com/code-cracker/code-cracker/) +Also, check the project [board](https://huboard.com/code-cracker/code-cracker/) and verify it is not being worked on (it will be tagged with the `Working` tag). -If it is not being worked on, before you start check if the item is `Ready`. +If it is not being worked on, check if the item is `Ready` before you start. If the issue has the `Working` tag (working swimlane on Huboard) and has no Assignee then it is not being worked on by somebody on the core team. Check the issue's description to find out who it is (if it is not there it has to be on the comments). @@ -108,7 +108,7 @@ be assigned to this team. The easiest way to start is looking into the issues that are [up for grabs](https://github.com/code-cracker/code-cracker/labels/up-for-grabs). You -may ask to work on any of them, read below to see how. You can also triage issues which may include reproducing bug reports, or asking for vital information such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to code-cracker on CodeTriage](https://www.codetriage.com/code-cracker/code-cracker). +may ask to work on any of them, read below to see how. You can also triage issues which may include reproducing bug reports or asking for vital information such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to code-cracker on CodeTriage](https://www.codetriage.com/code-cracker/code-cracker). If you are just starting with Roslyn, want to contribute, and feel you are not yet ready to start working on full analyzers or code fixes, you can start helping with areas that are @@ -116,8 +116,7 @@ less demanding. We have identified a few: * Fixing bugs - Still demands knowledge of Roslyn internals but it is easier than coming up with a full - analyzer or code fix. Look for the [bugs that are up for grabs](https://github.com/code-cracker/code-cracker/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Abug+label%3Aup-for-grabs). + Still demands knowledge of Roslyn internals but it is easier than coming up with a full analyzer or code fix. Look for the [bugs that are up for grabs](https://github.com/code-cracker/code-cracker/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Abug+label%3Aup-for-grabs). * Documentation @@ -126,10 +125,8 @@ less demanding. We have identified a few: * Localization/Translation - We are starting to translate the analyzers and code fixes messages to other languages. If you want CodeCracker - on your language feel free to create an issue and start working on it. If you want to help with an ongoing translation, - comment on the existing issue and say you are ready to help. We also need to update existing analyzers, which were - not created ready for localization. + We are starting to translate the analyzers and code fixes messages to other languages. If you want CodeCracker on your language feel free to create an issue and start working on it. If you want to help with an ongoing translation, + comment on the existing issue and say you are ready to help. We also need to update existing analyzers, which were not created ready for localization. ## Issues and task board @@ -145,7 +142,7 @@ defined ready as: 2. If it has an analyzer then 1. The warning level of the analyzer must be in the issue's description (`Hidden`, `Information`, `Warning`, or `Error`) - 2. The diagnostics it provides should already have numeric ids defined formated as `CC0000`. + 2. The diagnostics it provides should already have numeric ids defined formatted as `CC0000`. 3. If it has a code fix then the category should be in the issue's description. The supported categories are listed on the `SupportedCategories.cs` file. 4. Have some of the maintainers verify it (cannot be the same one who wrote the issue and/or test cases) @@ -161,9 +158,9 @@ and [#10](https://github.com/code-cracker/code-cracker/issues/10). These are the 4 severity levels supported on Roslyn and how they are understood on the Code Cracker project: 1. **Hidden**: Only used for refactorings. See #66 (and its comments) to understand why. -2. **Info**: An alternative way (ex: replacing for with foreach). Clearly a matter of opinion and/or current way could be correct, or maybe the new code could be correct. We cannot determine. +2. **Info**: An alternative way (ex: replacing for with foreach). Clearly, a matter of opinion and/or current way could be correct, or maybe the new code could be correct. We cannot determine. 3. **Warning**: Code that could/should be improved. It is a code smell and most likely is wrong, but there are situations where the pattern is acceptable or desired. -4. **Error**: Clearly a mistake (ex: throwing ArgumentException with an non-existent parameter). There is no situation where this code could be correct. There are no differences of opinion. +4. **Error**: Clearly a mistake (ex: throwing ArgumentException with a non-existent parameter). There is no situation where this code could be correct. There are no differences of opinion. You can read [directly on Microsoft's source code](http://source.roslyn.codeplex.com/#Microsoft.CodeAnalysis/Diagnostic/DiagnosticSeverity.cs,e70281df673d47f6,references) how they interpret these levels. @@ -182,7 +179,7 @@ The DoD is still evolving. At the present time the checklist is as follows: 5. Code fixes should follow the guidelines for names 1. Always named `CodeFixProvider` - 2. Always use the same diagnostic id added to the `DiagnosticIds.cs` file, unless you are writing a code fix for a diagnostic id raised by the C# compiler itself (staring with `CS`). + 2. Always use the same diagnostic id added to the `DiagnosticIds.cs` file, unless you are writing a code fix for a diagnostic id raised by the C# compiler itself (starting with `CS`). 6. Fix all scenarios (fix all in document, fix all in project and fix all in solution) work. You might need to write a `FixAllProvider`. Check the `DisposableVariableNotDisposedFixAllProvider` as an example. 7. Follow the coding standards present on the project code files. 8. Works in Visual Studio @@ -190,11 +187,11 @@ The DoD is still evolving. At the present time the checklist is as follows: ### Start working -Once it is Ready and agreed on by any one from the core team, just state in +Once it is Ready and agreed on by anyone from the core team, just state in a comment that you intend to start working on that item and mention any/all the maintainers (use @code-cracker/owners) so they can tag it correctly and move it on the board. -If you are not familiar with the way Github works you might want to check the [Github guides](https://guides.github.com/), specially +If you are not familiar with the way Github works you might want to check the [Github guides](https://guides.github.com/), especially the [Github flow](https://guides.github.com/introduction/flow/) one. The [GitHub for the Roslyn Team video](http://channel9.msdn.com/Blogs/dotnet/github-for-the-roslyn-team) might help you as well, and it also explains some Git concepts. @@ -203,7 +200,7 @@ To start working fork the project on Github to your own account and clone it **f from the main CodeCracker repository. Before you start coding create a new branch and name it in a way that makes sense for the issue that you will be working on. Don't work on the `master` branch because that may make things harder if you have to update your pull request or your repository later, assume your `master` branch -is always equals the main repo `master` branch, and code on a different branch. +always equals the main repo `master` branch, and code on a different branch. When you commit, mention the issue number use the pound sign (#). Avoid making a lot of small commits unless they are meaningful. For most analyzers and code fixes a single commit should be enough. If you @@ -239,9 +236,9 @@ git merge master # solve integration conflicts ```` -You can solve the conflicts in your favorite text editor, or, if you are using Visual Studio, you can use it as well. +You can solve the conflicts in your favorite text editor or Visual Studio. Visual Studio actually presents the conflict in a very nice way to solve them. -Also, on the `go back to your working branch` step you can go back to using Visual Studio to control git, if you +Also, on the `go back to your working branch` step you can go back to using Visual Studio to control git if you prefer that. If you know git well, you can rebase your changes instead of merging them. If not, it is ok to merge them. @@ -270,7 +267,7 @@ discussing and fixing they are accepted. Work with the community to get it to be * Your pull requested will be commented by the Coveralls bot. Make sure code coverage has not gone down significantly. Ideally, it should go up. If you work on something that you have not yet discussed with the maintainers -there is a chance the code might be denied because they might find the analyzer/fix is not necessary, or duplicated, or some other reason. +there is a chance the code might be denied because they might find the analyzer/fix is not necessary, duplicated, or some other reason. They are easily reachable through Twitter or on Github. Before you code discuss it with it them. Small code changes or updates outside code files will eventually be made by the core team directly on `master`, without a PR. @@ -284,7 +281,7 @@ Small code changes or updates outside code files will eventually be made by the Contributors can be found at the [contributors](https://github.com/code-cracker/code-cracker/graphs/contributors) page on Github. -### What are the maintainers responsibilities? +### What are the maintainers' responsibilities? The maintainers have to: @@ -307,5 +304,5 @@ Please see our [contact page](http://code-cracker.github.io/contact.html). This software is open source, licensed under the Apache License, Version 2.0. See [LICENSE.txt](https://github.com/code-cracker/code-cracker/blob/master/LICENSE.txt) for details. Check out the terms of the license before you contribute, fork, copy or do anything -with the code. If you decide to contribute you agree to grant copyright of all your contribution to this project, and agree to +with the code. If you decide to contribute you agree to grant copyright of all your contribution to this project and agree to mention clearly if do not agree to these terms. Your work will be licensed with the project at Apache V2, along the rest of the code. From cd95c2f4b39fdd979ae103f4e47b353185769236 Mon Sep 17 00:00:00 2001 From: Manish17292000 <43097382+Manish17292000@users.noreply.github.com> Date: Tue, 2 Oct 2018 19:34:38 +0530 Subject: [PATCH 211/234] Create hello.cpp --- hello.cpp | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 hello.cpp diff --git a/hello.cpp b/hello.cpp new file mode 100644 index 000000000..5df26f4c2 --- /dev/null +++ b/hello.cpp @@ -0,0 +1,7 @@ +#include + +int main() +{ + std::cout << "Hello, World!"; + return 0; +} From 7ad7ad8f1bf9d7af9f08fbee754df73d3bbd0486 Mon Sep 17 00:00:00 2001 From: Carl Troll Date: Sat, 6 Oct 2018 13:19:27 +0200 Subject: [PATCH 212/234] Enhancement for #922 --- .../Style/TaskNameAsyncCodeFixProvider.cs | 29 +++- .../Style/TaskNameASyncTests.cs | 132 ++++++++++++++++++ 2 files changed, 159 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs index 198444fb5..01b9aa6d3 100644 --- a/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/TaskNameAsyncCodeFixProvider.cs @@ -12,7 +12,7 @@ namespace CodeCracker.CSharp.Style { - [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(TaskNameAsyncCodeFixProvider)), Shared] + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CodeFixProvider)), Shared] public class TaskNameAsyncCodeFixProvider : CodeFixProvider { public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.TaskNameAsync.ToDiagnosticId()); @@ -46,7 +46,12 @@ private static async Task ChangeMethodNameAsync(Document document, Dia var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var methodStatement = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent.AncestorsAndSelf().OfType().First(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - var newName = methodStatement.Identifier.ToString() + "Async"; + var oldName = methodStatement.Identifier.ToString(); + if (HasAsyncCorrectlyInName(oldName)) + { + oldName = oldName.Remove(oldName.IndexOf("Async"), "Async".Length); + } + var newName = oldName + "Async"; var solution = document.Project.Solution; var symbol = semanticModel.GetDeclaredSymbol(methodStatement, cancellationToken); var options = solution.Workspace.Options; @@ -54,5 +59,25 @@ private static async Task ChangeMethodNameAsync(Document document, Dia options, cancellationToken).ConfigureAwait(false); return newSolution; } + + private static bool HasAsyncCorrectlyInName(string name) + { + var index = name.IndexOf("Async"); + if (index < 0) + { + return false; + } + + var postAsyncLetterIndex = index + "Async".Length; + if (postAsyncLetterIndex >= name.Length) + { + return false; + } + + var valueAfterAsync = name[postAsyncLetterIndex]; + return char.IsDigit(valueAfterAsync) + || (char.IsLetter(valueAfterAsync) && char.IsUpper(valueAfterAsync)) + || valueAfterAsync == '_'; + } } } \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs index e897d37b1..8074e4809 100644 --- a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs @@ -262,5 +262,137 @@ Task IBar.Foo() }; await VerifyCSharpDiagnosticAsync(source, expected); } + + [Fact] + public async Task ChangeTaskNameWithAsyncNotAtTheEndWithUpperCaseLetter() + { + const string source = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public class Foo + { + public methodTest() + { + await Test(); + } + + public Task TestAsyncFoo() + { + return true; + } + } + + }"; + const string fixtest = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public class Foo + { + public methodTest() + { + await TestAsync(); + } + + public Task TestFooAsync() + { + return true; + } + } + + }"; + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task ChangeTaskNameWithAsyncNotAtTheEndWithUnderline() + { + const string source = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public class Foo + { + public methodTest() + { + await Test(); + } + + public Task TestAsync_Foo() + { + return true; + } + } + + }"; + const string fixtest = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public class Foo + { + public methodTest() + { + await TestAsync(); + } + + public Task Test_FooAsync() + { + return true; + } + } + + }"; + await VerifyCSharpFixAsync(source, fixtest); + } + + [Fact] + public async Task ChangeTaskNameWithAsyncNotAtTheEndWithDigit() + { + const string source = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public class Foo + { + public methodTest() + { + await Test(); + } + + public Task TestAsync0Foo() + { + return true; + } + } + + }"; + const string fixtest = @" + using System.Threading.Tasks; + + namespace ConsoleApplication1 + { + public class Foo + { + public methodTest() + { + await TestAsync(); + } + + public Task Test0FooAsync() + { + return true; + } + } + + }"; + await VerifyCSharpFixAsync(source, fixtest); + } } } \ No newline at end of file From 8beb4cddaef68c447fab64f79dcd09ef7f61bf62 Mon Sep 17 00:00:00 2001 From: Carl Troll Date: Sat, 6 Oct 2018 14:18:27 +0200 Subject: [PATCH 213/234] #922 test fix --- .../CodeCracker.Test/Style/TaskNameASyncTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs index 8074e4809..44299b862 100644 --- a/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/TaskNameASyncTests.cs @@ -275,7 +275,7 @@ public class Foo { public methodTest() { - await Test(); + await TestAsyncFoo(); } public Task TestAsyncFoo() @@ -294,7 +294,7 @@ public class Foo { public methodTest() { - await TestAsync(); + await TestFooAsync(); } public Task TestFooAsync() @@ -319,7 +319,7 @@ public class Foo { public methodTest() { - await Test(); + await TestAsync_Foo(); } public Task TestAsync_Foo() @@ -338,7 +338,7 @@ public class Foo { public methodTest() { - await TestAsync(); + await Test_FooAsync(); } public Task Test_FooAsync() @@ -363,7 +363,7 @@ public class Foo { public methodTest() { - await Test(); + await TestAsync0Foo(); } public Task TestAsync0Foo() @@ -382,7 +382,7 @@ public class Foo { public methodTest() { - await TestAsync(); + await Test0FooAsync(); } public Task Test0FooAsync() From 9b66639413cbf1afdfe52e2acc107446c6f5b1da Mon Sep 17 00:00:00 2001 From: Carl Troll Date: Mon, 8 Oct 2018 10:16:02 +0200 Subject: [PATCH 214/234] Make CC0011 work with IQueryable and Async methods --- .../RemoveWhereWhenItIsPossibleAnalyzer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs index aa7fbda5e..a38da9608 100644 --- a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs @@ -25,8 +25,17 @@ public class RemoveWhereWhenItIsPossibleAnalyzer : DiagnosticAnalyzer "Any", "Single", "SingleOrDefault", - "Count" + "Count", + "FirstAsync", + "FirstOrDefaultAsync", + "LastAsync", + "LastOrDefaultAsync", + "AnyAsync", + "SingleAsync", + "SingleOrDefaultAsync", + "CountAsync" }; + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), Title, From 965944d0557db706cab329f576d2e6599c681424 Mon Sep 17 00:00:00 2001 From: carlilord Date: Mon, 8 Oct 2018 10:26:05 +0200 Subject: [PATCH 215/234] Delete RemoveWhereWhenItIsPossibleAnalyzer.cs --- .../RemoveWhereWhenItIsPossibleAnalyzer.cs | 90 ------------------- 1 file changed, 90 deletions(-) delete mode 100644 src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs diff --git a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs deleted file mode 100644 index a38da9608..000000000 --- a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace CodeCracker.CSharp.Performance -{ - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public class RemoveWhereWhenItIsPossibleAnalyzer : DiagnosticAnalyzer - { - internal const string Title = "You should remove the 'Where' invocation when it is possible."; - internal const string MessageFormat = "You can remove 'Where' moving the predicate to '{0}'."; - internal const string Category = SupportedCategories.Performance; - const string Description = "When a linq operator support a predicate parameter it should be used instead of " - + "using 'Where' followed by the operator"; - - static readonly string[] supportedMethods = new[] { - "First", - "FirstOrDefault", - "Last", - "LastOrDefault", - "Any", - "Single", - "SingleOrDefault", - "Count", - "FirstAsync", - "FirstOrDefaultAsync", - "LastAsync", - "LastOrDefaultAsync", - "AnyAsync", - "SingleAsync", - "SingleOrDefaultAsync", - "CountAsync" - }; - - internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( - DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), - Title, - MessageFormat, - Category, - DiagnosticSeverity.Warning, - isEnabledByDefault: true, - description: Description, - helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.RemoveWhereWhenItIsPossible)); - - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); - - public override void Initialize(AnalysisContext context) => - context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.InvocationExpression); - - private static void AnalyzeNode(SyntaxNodeAnalysisContext context) - { - if (context.IsGenerated()) return; - var whereInvoke = (InvocationExpressionSyntax)context.Node; - var nameOfWhereInvoke = GetNameOfTheInvokedMethod(whereInvoke); - if (nameOfWhereInvoke?.ToString() != "Where") return; - if (ArgumentsDoNotMatch(whereInvoke)) return; - - var nextMethodInvoke = whereInvoke.Parent. - FirstAncestorOrSelf(); - if (nextMethodInvoke == null) return; - - var candidate = GetNameOfTheInvokedMethod(nextMethodInvoke)?.ToString(); - if (!supportedMethods.Contains(candidate)) return; - - if (nextMethodInvoke.ArgumentList.Arguments.Any()) return; - var properties = new Dictionary { { "methodName", candidate } }.ToImmutableDictionary(); - var diagnostic = Diagnostic.Create(Rule, nameOfWhereInvoke.GetLocation(), properties, candidate); - context.ReportDiagnostic(diagnostic); - } - - private static bool ArgumentsDoNotMatch(InvocationExpressionSyntax whereInvoke) - { - var arguments = whereInvoke.ArgumentList.Arguments; - if (arguments.Count != 1) return true; - var expression = arguments.First()?.Expression; - if (expression == null) return true; - if (expression is SimpleLambdaExpressionSyntax) return false; - var parenthesizedLambda = expression as ParenthesizedLambdaExpressionSyntax; - if (parenthesizedLambda == null) return true; - return parenthesizedLambda.ParameterList.Parameters.Count != 1; - } - - private static SimpleNameSyntax GetNameOfTheInvokedMethod(InvocationExpressionSyntax invoke) => - invoke.ChildNodes().OfType().FirstOrDefault()?.Name; - } -} \ No newline at end of file From a6c1d1b93a81efd3da2dfce464963e127a26f16d Mon Sep 17 00:00:00 2001 From: carlilord Date: Mon, 8 Oct 2018 10:28:24 +0200 Subject: [PATCH 216/234] Make CC0011 work with IQueryable and Async methods Fixes #905 --- .../RemoveWhereWhenItIsPossibleAnalyzer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs index aa7fbda5e..9ba262a53 100644 --- a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs @@ -25,8 +25,17 @@ public class RemoveWhereWhenItIsPossibleAnalyzer : DiagnosticAnalyzer "Any", "Single", "SingleOrDefault", - "Count" + "Count", + "FirstAsync", + "FirstOrDefaultAsync", + "LastAsync", + "LastOrDefaultAsync", + "AnyAsync", + "SingleAsync", + "SingleOrDefaultAsync", + "CountAsync" }; + internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), Title, @@ -78,4 +87,4 @@ private static bool ArgumentsDoNotMatch(InvocationExpressionSyntax whereInvoke) private static SimpleNameSyntax GetNameOfTheInvokedMethod(InvocationExpressionSyntax invoke) => invoke.ChildNodes().OfType().FirstOrDefault()?.Name; } -} \ No newline at end of file +} From ba0b8e496b24497a0b39cde87ce650e754c3547d Mon Sep 17 00:00:00 2001 From: Carl Troll Date: Mon, 8 Oct 2018 10:32:37 +0200 Subject: [PATCH 217/234] Revert --- .../Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs index a38da9608..1332ab9a1 100644 --- a/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs +++ b/src/CSharp/CodeCracker/Performance/RemoveWhereWhenItIsPossibleAnalyzer.cs @@ -25,15 +25,7 @@ public class RemoveWhereWhenItIsPossibleAnalyzer : DiagnosticAnalyzer "Any", "Single", "SingleOrDefault", - "Count", - "FirstAsync", - "FirstOrDefaultAsync", - "LastAsync", - "LastOrDefaultAsync", - "AnyAsync", - "SingleAsync", - "SingleOrDefaultAsync", - "CountAsync" + "Count" }; internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( From 9342e9f804712c7090eccdc11af93d7f3c9f98f3 Mon Sep 17 00:00:00 2001 From: Umang Raval Date: Mon, 8 Oct 2018 20:02:45 +0530 Subject: [PATCH 218/234] corrected grammatical errors --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bfb59721e..24b95237a 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ The DoD is still evolving. At the present time the checklist is as follows: 1. Always named `CodeFixProvider` 2. Always use the same diagnostic id added to the `DiagnosticIds.cs` file, unless you are writing a code fix for a diagnostic id raised by the C# compiler itself (starting with `CS`). -6. Fix all scenarios (fix all in document, fix all in project and fix all in solution) work. You might need to write a `FixAllProvider`. Check the `DisposableVariableNotDisposedFixAllProvider` as an example. +6. Fix all scenarios (fix all in a document, fix all in a project and fix all in solution) work. You might need to write a `FixAllProvider`. Check the `DisposableVariableNotDisposedFixAllProvider` as an example. 7. Follow the coding standards present on the project code files. 8. Works in Visual Studio 9. Uses localizable strings From c35c6cb1364267782a66c48e0578ee649dbecf6d Mon Sep 17 00:00:00 2001 From: Isuru40 Date: Sat, 20 Oct 2018 11:30:52 +0530 Subject: [PATCH 219/234] Update Hacktoberfest --- Hacktoberfest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hacktoberfest b/Hacktoberfest index 316700cd9..28c43036f 100644 --- a/Hacktoberfest +++ b/Hacktoberfest @@ -23,4 +23,4 @@ Create a remote to link the repository on github to your local workspace. use "g Push the commit. For example, type "git push [remote-name] master". Go back to the original repo. Hit "new pull request" and compare between forks. -Confirm the pull request and that's it! +Confirm the pull request and that's it!!! From 9ccc2bb21012d0845156af28fab4e56f15cd8474 Mon Sep 17 00:00:00 2001 From: Neil Bostrom Date: Sun, 18 Nov 2018 22:06:00 +0000 Subject: [PATCH 220/234] Fixes #930 CC0020 cannot be used when types are declared --- ...ertLambdaExpressionToMethodGroupAnalyzer.cs | 8 +++++++- ...onvertLambdaExpressionToMethodGroupTests.cs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Style/ConvertLambdaExpressionToMethodGroupAnalyzer.cs b/src/CSharp/CodeCracker/Style/ConvertLambdaExpressionToMethodGroupAnalyzer.cs index 671e55349..bb335f76d 100644 --- a/src/CSharp/CodeCracker/Style/ConvertLambdaExpressionToMethodGroupAnalyzer.cs +++ b/src/CSharp/CodeCracker/Style/ConvertLambdaExpressionToMethodGroupAnalyzer.cs @@ -65,7 +65,13 @@ internal static InvocationExpressionSyntax GetInvocationIfAny(SyntaxNode node) : (node as ParenthesizedLambdaExpressionSyntax)?.Body; var invocation = body as InvocationExpressionSyntax; - if (invocation != null) return invocation; + + if (invocation != null) + { + if (invocation.Expression is GenericNameSyntax && (((GenericNameSyntax)invocation.Expression).TypeArgumentList.Arguments.Count > 0)) return null; + + return invocation; + } var possibleBlock = body as BlockSyntax; if (possibleBlock == null || possibleBlock.Statements.Count != 1) return null; diff --git a/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs b/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs index 0a968adf9..f26fcd8b9 100644 --- a/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/ConvertLambdaExpressionToMethodGroupTests.cs @@ -598,5 +598,23 @@ public static Task Finally(this Task task, Func(); + xs.Select(x => Func(x)); + } + object Func(object x) => x; +}"; + await VerifyCSharpHasNoDiagnosticsAsync(oldCode); + } + } } \ No newline at end of file From 80f53b29811fdf36a57a8b8119eea8fc33f25456 Mon Sep 17 00:00:00 2001 From: carlilord Date: Fri, 23 Nov 2018 10:08:54 +0100 Subject: [PATCH 221/234] #905 added unit test --- .../CodeCracker.Test/CodeCracker.Test.csproj | 1 + .../Helpers/IQueriableExtensions.cs | 43 +++++ .../RemoveWhereWhenItIsPossibleTests.cs | 160 ++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 test/CSharp/CodeCracker.Test/Helpers/IQueriableExtensions.cs diff --git a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj index 4d186cfbe..7796725c8 100644 --- a/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj +++ b/test/CSharp/CodeCracker.Test/CodeCracker.Test.csproj @@ -120,6 +120,7 @@ + diff --git a/test/CSharp/CodeCracker.Test/Helpers/IQueriableExtensions.cs b/test/CSharp/CodeCracker.Test/Helpers/IQueriableExtensions.cs new file mode 100644 index 000000000..c37c9ebf4 --- /dev/null +++ b/test/CSharp/CodeCracker.Test/Helpers/IQueriableExtensions.cs @@ -0,0 +1,43 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeCracker.Test.CSharp.Helpers +{ + public static class IQueriableExtensions + { +#pragma warning disable CC0057 // Unused parameters + public static Task FirstAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => null; + + public static Task FirstOrDefaultAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => null; + + public static Task LastAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => null; + + public static Task LastOrDefaultAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => null; + + public static Task AnyAsync(this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => Task.FromResult(false); + + public static Task SingleAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => null; + + public static Task SingleOrDefaultAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => null; + + public static Task CountAsync( + this IQueryable source, + CancellationToken cancellationToken = default(CancellationToken)) => Task.FromResult(0); + +#pragma warning restore CC0057 // Unused parameters + } +} \ No newline at end of file diff --git a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs index c6e4b622a..17222105f 100644 --- a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs @@ -154,6 +154,166 @@ public async Task DoSomething() var expected = @" using System.Linq; +namespace Sample +{ + public class Foo + { + public async Task DoSomething() + { + var a = new int[10]; + var f = a.OrderBy(item => item)." + method + @"(item => item > 10); + } + } +}"; + + await VerifyCSharpFixAsync(test, expected); + + } + + // Async + [Theory] + [InlineData("FirstAsync")] + [InlineData("FirstOrDefaultAsync")] + [InlineData("LastAsync")] + [InlineData("LastOrDefaultAsync")] + [InlineData("AnyAsync")] + [InlineData("SingleAsync")] + [InlineData("SingleOrDefaultAsync")] + [InlineData("CountAsync")] + public async Task CreateDiagnosticWhenUsingWhereWithAsync(string method) + { + var test = @" +using System.Linq; + +namespace Sample +{ + public class Foo + { + public async Task DoSomething() + { + var a = new int[10]; + var f = a.Where(item => item > 10)." + method + @"(); + } + } +}"; + var expected = new DiagnosticResult + { + Id = DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), + Message = "You can remove 'Where' moving the predicate to '" + method + "'.", + Severity = DiagnosticSeverity.Warning, + Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 23) } + }; + + await VerifyCSharpDiagnosticAsync(test, expected); + + } + + [Theory] + [InlineData("FirstAsync")] + [InlineData("FirstOrDefaultAsync")] + [InlineData("LastAsync")] + [InlineData("LastOrDefaultAsync")] + [InlineData("AnyAsync")] + [InlineData("SingleAsync")] + [InlineData("SingleOrDefaultAsync")] + [InlineData("CountAsync")] + public async Task DoNotCreateDiagnosticWhenUsingWhereAndAnotherMethodWithPredicatesAsync(string method) + { + var test = @" +using System.Linq; + +namespace Sample +{ + public class Foo + { + public async Task DoSomething() + { + var a = new int[10]; + var f = a.Where(item => item > 10)." + method + @"(item => item < 50); + } + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Fact] + public async Task DoNotCreateDiagnosticWhenWhereUsesIndexerAsync() + { + var test = @" +var first = Enumerable.Range(1, 10).ToList(); +var second = Enumerable.Range(1, 10); +var isNotMatch = second.Where((t, i) => first[i] != t).Any(); +".WrapInCSharpMethod(usings: "using System.Linq;"); + await VerifyCSharpHasNoDiagnosticsAsync(test); + } + + [Theory] + [InlineData("FirstAsync")] + [InlineData("FirstOrDefaultAsync")] + [InlineData("LastAsync")] + [InlineData("LastOrDefaultAsync")] + [InlineData("AnyAsync")] + [InlineData("SingleAsync")] + [InlineData("SingleOrDefaultAsync")] + [InlineData("CountAsync")] + public async Task FixRemovesWhereMovingPredicateToAsync(string method) + { + var test = @" +namespace Sample +{ + public class Foo + { + public async Task DoSomething() + { + var a = new int[10]; + var f = a.Where((item) => item > 10)." + method + @"(); + } + } +}"; + var expected = @" +namespace Sample +{ + public class Foo + { + public async Task DoSomething() + { + var a = new int[10]; + var f = a." + method + @"((item) => item > 10); + } + } +}"; + await VerifyCSharpFixAsync(test, expected); + } + + [Theory] + [InlineData("FirstAsync")] + [InlineData("FirstOrDefaultAsync")] + [InlineData("LastAsync")] + [InlineData("LastOrDefaultAsync")] + [InlineData("AnyAsync")] + [InlineData("SingleAsync")] + [InlineData("SingleOrDefaultAsync")] + [InlineData("CountAsync")] + public async Task FixRemovesWherePreservingPreviousExpressionsMovingPredicateToAsync(string method) + { + var test = @" +using System.Linq; + +namespace Sample +{ + public class Foo + { + public async Task DoSomething() + { + var a = new int[10]; + var f = a.OrderBy(item => item).Where(item => item > 10)." + method + @"(); + } + } +}"; + + var expected = @" +using System.Linq; + namespace Sample { public class Foo From 1536af459849daac58cd182bfa2131c1ae5461a1 Mon Sep 17 00:00:00 2001 From: carlilord Date: Fri, 23 Nov 2018 10:20:07 +0100 Subject: [PATCH 222/234] build fix --- .../Performance/RemoveWhereWhenItIsPossibleTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs index 17222105f..3d55fa490 100644 --- a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs @@ -170,7 +170,6 @@ public async Task DoSomething() } - // Async [Theory] [InlineData("FirstAsync")] [InlineData("FirstOrDefaultAsync")] From ee521d7400df52b4f3e7734297d44111b0b4c2a9 Mon Sep 17 00:00:00 2001 From: carlilord Date: Fri, 23 Nov 2018 10:23:10 +0100 Subject: [PATCH 223/234] test adaption --- .../RemoveWhereWhenItIsPossibleTests.cs | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs index 3d55fa490..a953a1360 100644 --- a/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs +++ b/test/CSharp/CodeCracker.Test/Performance/RemoveWhereWhenItIsPossibleTests.cs @@ -170,43 +170,6 @@ public async Task DoSomething() } - [Theory] - [InlineData("FirstAsync")] - [InlineData("FirstOrDefaultAsync")] - [InlineData("LastAsync")] - [InlineData("LastOrDefaultAsync")] - [InlineData("AnyAsync")] - [InlineData("SingleAsync")] - [InlineData("SingleOrDefaultAsync")] - [InlineData("CountAsync")] - public async Task CreateDiagnosticWhenUsingWhereWithAsync(string method) - { - var test = @" -using System.Linq; - -namespace Sample -{ - public class Foo - { - public async Task DoSomething() - { - var a = new int[10]; - var f = a.Where(item => item > 10)." + method + @"(); - } - } -}"; - var expected = new DiagnosticResult - { - Id = DiagnosticId.RemoveWhereWhenItIsPossible.ToDiagnosticId(), - Message = "You can remove 'Where' moving the predicate to '" + method + "'.", - Severity = DiagnosticSeverity.Warning, - Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 23) } - }; - - await VerifyCSharpDiagnosticAsync(test, expected); - - } - [Theory] [InlineData("FirstAsync")] [InlineData("FirstOrDefaultAsync")] From 62c719a8526fe68d7c1707ea690d4736c56b3fe1 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 4 Jan 2019 16:22:19 +0100 Subject: [PATCH 224/234] Insert missing link Insert missing link to issue #66 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24b95237a..d30381db7 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ and [#10](https://github.com/code-cracker/code-cracker/issues/10). These are the 4 severity levels supported on Roslyn and how they are understood on the Code Cracker project: -1. **Hidden**: Only used for refactorings. See #66 (and its comments) to understand why. +1. **Hidden**: Only used for refactorings. See [#66](https://github.com/code-cracker/code-cracker/issues/66) (and its comments) to understand why. 2. **Info**: An alternative way (ex: replacing for with foreach). Clearly, a matter of opinion and/or current way could be correct, or maybe the new code could be correct. We cannot determine. 3. **Warning**: Code that could/should be improved. It is a code smell and most likely is wrong, but there are situations where the pattern is acceptable or desired. 4. **Error**: Clearly a mistake (ex: throwing ArgumentException with a non-existent parameter). There is no situation where this code could be correct. There are no differences of opinion. From cda01dbd1c28f8c5bdbc0cfd13bf8cca40aeaa0a Mon Sep 17 00:00:00 2001 From: Matthieu Penant Date: Wed, 3 Apr 2019 11:54:45 -0400 Subject: [PATCH 225/234] VS2019 Support fix the errors on prerequisites --- .../CodeCracker.Vsix/debug/source.extension.vsixmanifest | 4 ++-- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 4 ++-- .../CodeCracker.Vsix/debug/source.extension.vsixmanifest | 4 ++-- .../CodeCracker.Vsix/source.extension.vsixmanifest | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CSharp/CodeCracker.Vsix/debug/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/debug/source.extension.vsixmanifest index e81a560f6..e0b59f52d 100644 --- a/src/CSharp/CodeCracker.Vsix/debug/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/debug/source.extension.vsixmanifest @@ -28,7 +28,7 @@ This is a community project, free and open source. Everyone is invited to contri - - + + diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index aa1218012..7931195c2 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -27,7 +27,7 @@ This is a community project, free and open source. Everyone is invited to contri - - + + diff --git a/src/VisualBasic/CodeCracker.Vsix/debug/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/debug/source.extension.vsixmanifest index 6f6ab34bd..0595693d0 100644 --- a/src/VisualBasic/CodeCracker.Vsix/debug/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/debug/source.extension.vsixmanifest @@ -28,7 +28,7 @@ This is a community project, free and open source. Everyone is invited to contri - - + + diff --git a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest index 3de517a30..01fa41c09 100644 --- a/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/VisualBasic/CodeCracker.Vsix/source.extension.vsixmanifest @@ -27,7 +27,7 @@ This is a community project, free and open source. Everyone is invited to contri - - + + From b706ff895d3fbeba106b3146b62d4d84002b5e7c Mon Sep 17 00:00:00 2001 From: Mithilesh Zavar Date: Sat, 6 Apr 2019 19:36:12 +0100 Subject: [PATCH 226/234] BUG: CC0065 "Remove trailing whitespace" bug with pragmas --- .../RemoveTrailingWhitespaceCodeFixProvider.cs | 2 +- .../Style/RemoveTrailingWhitespaceTests.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker/Style/RemoveTrailingWhitespaceCodeFixProvider.cs b/src/CSharp/CodeCracker/Style/RemoveTrailingWhitespaceCodeFixProvider.cs index 0190ed41b..b4a94ff25 100644 --- a/src/CSharp/CodeCracker/Style/RemoveTrailingWhitespaceCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Style/RemoveTrailingWhitespaceCodeFixProvider.cs @@ -35,7 +35,7 @@ private static async Task RemoveTrailingWhiteSpaceAsync(Document docum { newRoot = root.ReplaceTrivia(trivia, new SyntaxTrivia[] { }); } - else if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia, SyntaxKind.MultiLineDocumentationCommentTrivia)) + else if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia, SyntaxKind.MultiLineDocumentationCommentTrivia, SyntaxKind.PragmaWarningDirectiveTrivia)) { var commentText = trivia.ToFullString(); var commentLines = commentText.Split(new[] { Environment.NewLine }, StringSplitOptions.None); diff --git a/test/CSharp/CodeCracker.Test/Style/RemoveTrailingWhitespaceTests.cs b/test/CSharp/CodeCracker.Test/Style/RemoveTrailingWhitespaceTests.cs index de6b62bae..2130d04d4 100644 --- a/test/CSharp/CodeCracker.Test/Style/RemoveTrailingWhitespaceTests.cs +++ b/test/CSharp/CodeCracker.Test/Style/RemoveTrailingWhitespaceTests.cs @@ -135,5 +135,21 @@ class Foo { }"; class Foo { }"; await VerifyCSharpFixAsync(source, expected, formatBeforeCompare: false); } + + [Fact] + public async Task PragmaWithTrailingSpace() + { + const string source = @" +#pragma warning disable CC0072 +#pragma warning restore CC0072 +"; + + const string expected = @" +#pragma warning disable CC0072 +#pragma warning restore CC0072 +"; + + await VerifyCSharpFixAsync(source, expected, formatBeforeCompare: false); + } } } \ No newline at end of file From 5d274c23236037ef02168eef7a27a0d2be169484 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Mon, 27 May 2019 14:19:35 +0200 Subject: [PATCH 227/234] Add property name to ExportCodeFixProviderAttribute. --- .../Design/StaticConstructorExceptionCodeFixProvider.cs | 2 +- .../XmlDocumentationMissingInCSharpCodeFixProvider.cs | 2 +- .../XmlDocumentationMissingInXmlCodeFixProvider.cs | 2 +- .../Refactoring/StringRepresentationCodeFixProvider.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CSharp/CodeCracker/Design/StaticConstructorExceptionCodeFixProvider.cs b/src/CSharp/CodeCracker/Design/StaticConstructorExceptionCodeFixProvider.cs index 38d620ba6..44ff21625 100644 --- a/src/CSharp/CodeCracker/Design/StaticConstructorExceptionCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Design/StaticConstructorExceptionCodeFixProvider.cs @@ -10,7 +10,7 @@ namespace CodeCracker.CSharp.Design { - [ExportCodeFixProvider(LanguageNames.CSharp, nameof(StaticConstructorExceptionCodeFixProvider)), Shared] + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(StaticConstructorExceptionCodeFixProvider)), Shared] public class StaticConstructorExceptionCodeFixProvider : CodeFixProvider { public sealed override ImmutableArray FixableDiagnosticIds => diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs index 232533605..b0d5f4e9d 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInCSharpCodeFixProvider.cs @@ -12,7 +12,7 @@ namespace CodeCracker.CSharp.Maintainability { - [ExportCodeFixProvider(LanguageNames.CSharp, nameof(XmlDocumentationCodeFixProvider)), Shared] + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(XmlDocumentationCodeFixProvider)), Shared] public sealed class XmlDocumentationMissingInCSharpCodeFixProvider : XmlDocumentationCodeFixProvider { public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId()); diff --git a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs index be54bc846..36e268fca 100644 --- a/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Maintainability/XmlDocumentationMissingInXmlCodeFixProvider.cs @@ -12,7 +12,7 @@ namespace CodeCracker.CSharp.Maintainability { - [ExportCodeFixProvider(LanguageNames.CSharp, nameof(XmlDocumentationCodeFixProvider)), Shared] + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(XmlDocumentationCodeFixProvider)), Shared] public sealed class XmlDocumentationMissingInXmlCodeFixProvider : XmlDocumentationCodeFixProvider { public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId()); diff --git a/src/CSharp/CodeCracker/Refactoring/StringRepresentationCodeFixProvider.cs b/src/CSharp/CodeCracker/Refactoring/StringRepresentationCodeFixProvider.cs index 3f1934ac1..bd8d714c6 100644 --- a/src/CSharp/CodeCracker/Refactoring/StringRepresentationCodeFixProvider.cs +++ b/src/CSharp/CodeCracker/Refactoring/StringRepresentationCodeFixProvider.cs @@ -13,7 +13,7 @@ namespace CodeCracker.CSharp.Refactoring { - [ExportCodeFixProvider(LanguageNames.CSharp, nameof(StringRepresentationCodeFixProvider)), Shared] + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(StringRepresentationCodeFixProvider)), Shared] public class StringRepresentationCodeFixProvider : CodeFixProvider { public const string Id = nameof(StringRepresentationCodeFixProvider); From cf422cc5031c13659250f2ad44a82d1f350ce2b5 Mon Sep 17 00:00:00 2001 From: sunny kumar Date: Tue, 1 Oct 2019 13:10:35 +0530 Subject: [PATCH 228/234] Change : added << endl in hello.cpp --- hello.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hello.cpp b/hello.cpp index 5df26f4c2..378706961 100644 --- a/hello.cpp +++ b/hello.cpp @@ -2,6 +2,6 @@ int main() { - std::cout << "Hello, World!"; + std::cout << "Hello, World!" << endl; return 0; } From 83f23667f3cb5748d979ece4158ef53ce83cccbf Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Thu, 21 Nov 2019 14:26:55 -0300 Subject: [PATCH 229/234] Version 2019 --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index 7931195c2..b3b107180 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + Code Cracker for C# An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. From 5cab9bfd2aabf83e687377ecfdbf9762db9880cd Mon Sep 17 00:00:00 2001 From: Carlos dos Santos Date: Thu, 21 Nov 2019 14:41:30 -0300 Subject: [PATCH 230/234] VSIX 2019 --- src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest index b3b107180..a495c36ac 100644 --- a/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest +++ b/src/CSharp/CodeCracker.Vsix/source.extension.vsixmanifest @@ -2,7 +2,7 @@ - Code Cracker for C# + Code Cracker for C# (2019) An analyzer library for C# that uses Roslyn to produce refactorings, code analysis, and other niceties. Check the official project site on code-cracker.github.io. Build status Nuget count Nuget downloads Issues open From 2e44309a8dd7febcf9e2fb1d85c0ed17734d3082 Mon Sep 17 00:00:00 2001 From: "dsharov@devpark.ru" Date: Tue, 22 Mar 2022 17:39:58 +0600 Subject: [PATCH 231/234] Added parser for inline using --- .../DisposableVariableNotDisposedAnalyzer.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs index 3ed958b5f..83544effa 100644 --- a/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/DisposableVariableNotDisposedAnalyzer.cs @@ -78,6 +78,28 @@ private static void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context) var usingStatement = variableDeclaration?.Parent as UsingStatementSyntax; if (usingStatement != null) return; statement = variableDeclaration.Parent as LocalDeclarationStatementSyntax; + if (statement != null) + { + //Check inline using + var isUsing = false; + var isSemicolon = false; + var firstToken = statement.GetFirstToken(); + if (firstToken != null) + { + isUsing = firstToken.Text == "using"; + } + + var lastToken = statement.GetLastToken(); + if (lastToken != null) + { + isSemicolon = lastToken.Text == ";"; + } + + var isVariableDeclaration = statement.ChildNodes().First() is VariableDeclarationSyntax; + + if (isUsing && isVariableDeclaration && isSemicolon) return; + } + if ((statement?.FirstAncestorOrSelf()) == null) return; } else if (topSyntaxNode.Parent.IsAnyKind(SyntaxKind.SimpleLambdaExpression, SyntaxKind.ParenthesizedLambdaExpression)) From a3536314991e0e8958348388a3581526d98b8a9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jun 2022 00:01:24 +0000 Subject: [PATCH 232/234] Bump NuGet.CommandLine from 4.6.2 to 4.9.5 in /.nuget Bumps NuGet.CommandLine from 4.6.2 to 4.9.5. --- updated-dependencies: - dependency-name: NuGet.CommandLine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .nuget/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nuget/packages.config b/.nuget/packages.config index b1704a67b..87d34f8af 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -1,6 +1,6 @@  - + From 39202fbde4d63a722519cb2847b9b8ba7bb0dc9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Dec 2022 01:35:12 +0000 Subject: [PATCH 233/234] Bump Newtonsoft.Json in /test/Common/CodeCracker.Test.Common Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 11.0.2 to 13.0.2. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/11.0.2...13.0.2) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../CodeCracker.Test.Common/CodeCracker.Test.Common.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj index ee17f57f6..ab8625db9 100644 --- a/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj +++ b/test/Common/CodeCracker.Test.Common/CodeCracker.Test.Common.csproj @@ -48,7 +48,7 @@ - + From 15a265d6e8c1566ad145df8bfcb252753a1c43e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 22:56:09 +0000 Subject: [PATCH 234/234] Bump NuGet.CommandLine from 4.9.5 to 5.11.5 in /.nuget Bumps [NuGet.CommandLine](https://github.com/NuGet/NuGet.Client) from 4.9.5 to 5.11.5. - [Release notes](https://github.com/NuGet/NuGet.Client/releases) - [Commits](https://github.com/NuGet/NuGet.Client/commits) --- updated-dependencies: - dependency-name: NuGet.CommandLine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .nuget/packages.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.nuget/packages.config b/.nuget/packages.config index 87d34f8af..ac480de76 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -1,6 +1,6 @@ - + - +