From 03ff4555788147dad6600998fba60031ea3d9ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Mon, 14 Feb 2022 09:14:38 +0100 Subject: [PATCH 01/16] Add editorconfig with tuned configuration (#1300) Add editorconfig with tuned configuration --- .editorconfig | 197 ++++++++++++++++++ Directory.Build.props | 5 +- coverlet.sln | 9 +- .../DataCollection/AttachmentManager.cs | 16 +- .../DataCollection/CoverageManager.cs | 9 +- .../DataCollection/CoverageWrapper.cs | 5 +- .../CoverletCoverageCollector.cs | 11 +- .../DataCollection/CoverletLogger.cs | 4 +- .../DataCollection/CoverletSettings.cs | 5 +- .../DataCollection/CoverletSettingsParser.cs | 21 +- .../CoverletInProcDataCollector.cs | 14 +- .../Properties/AssemblyInfo.cs | 3 + .../Utilities/CountDownEvent.cs | 6 +- .../Utilities/CoverletConstants.cs | 5 +- .../CoverletDataCollectorException.cs | 5 +- .../Utilities/DirectoryHelper.cs | 5 +- .../Utilities/FileHelper.cs | 5 +- .../Utilities/Interfaces/ICountDown.cs | 5 +- .../Utilities/Interfaces/ICoverageWrapper.cs | 5 +- .../Utilities/Interfaces/IDirectoryHelper.cs | 5 +- .../Utilities/Interfaces/IFileHelper.cs | 5 +- .../Utilities/TestPlatformEqtTrace.cs | 5 +- .../Utilities/TestPlatformLogger.cs | 5 +- .../ConsoleTables/.editorconfig | 8 + src/coverlet.console/ExitCodes.cs | 5 +- src/coverlet.console/Logging/ConsoleLogger.cs | 5 +- src/coverlet.console/Logging/LogLevel.cs | 3 + src/coverlet.console/Program.cs | 80 +++---- .../Properties/AssemblyInfo.cs | 3 + .../Abstractions/ICecilSymbolHelper.cs | 5 +- src/coverlet.core/Abstractions/IConsole.cs | 5 +- src/coverlet.core/Abstractions/IFileSystem.cs | 5 +- .../Abstractions/IInstrumentationHelper.cs | 5 +- src/coverlet.core/Abstractions/ILogger.cs | 3 + .../Abstractions/IProcessExitHandler.cs | 5 +- src/coverlet.core/Abstractions/IReporter.cs | 3 + .../Abstractions/IRetryHelper.cs | 5 +- .../Abstractions/ISourceRootTranslator.cs | 5 +- .../Attributes/DoesNotReturnAttribute.cs | 5 +- .../Attributes/ExcludeFromCoverage.cs | 3 + src/coverlet.core/Coverage.cs | 110 +++++----- src/coverlet.core/CoverageDetails.cs | 3 + src/coverlet.core/CoveragePrepareResult.cs | 7 +- src/coverlet.core/CoverageResult.cs | 56 ++--- src/coverlet.core/CoverageSummary.cs | 71 ++++--- src/coverlet.core/Enums/ThresholdStatistic.cs | 3 + src/coverlet.core/Enums/ThresholdTypeFlags.cs | 3 + src/coverlet.core/Exceptions.cs | 5 +- .../Extensions/HelperExtensions.cs | 6 +- src/coverlet.core/Helpers/Console.cs | 4 +- src/coverlet.core/Helpers/FileSystem.cs | 5 +- .../Helpers/InstrumentationHelper.cs | 58 +++--- .../Helpers/ProcessExitHandler.cs | 5 +- src/coverlet.core/Helpers/RetryHelper.cs | 7 +- .../Helpers/SourceRootTranslator.cs | 11 +- .../Instrumentation/CecilAssemblyResolver.cs | 12 +- .../Instrumentation/Instrumenter.cs | 112 +++++----- .../Instrumentation/InstrumenterResult.cs | 7 +- .../Instrumentation/ModuleTrackerTemplate.cs | 12 +- .../Instrumentation/ReachabilityHelper.cs | 131 ++++++------ src/coverlet.core/Properties/AssemblyInfo.cs | 3 + .../Reporters/CoberturaReporter.cs | 55 ++--- src/coverlet.core/Reporters/JsonReporter.cs | 7 +- src/coverlet.core/Reporters/LcovReporter.cs | 30 +-- .../Reporters/OpenCoverReporter.cs | 104 ++++----- .../Reporters/ReporterFactory.cs | 10 +- .../Reporters/TeamCityReporter.cs | 12 +- src/coverlet.core/Symbols/BranchPoint.cs | 4 +- .../Symbols/CecilSymbolHelper.cs | 91 ++++---- src/coverlet.msbuild.tasks/BaseTask.cs | 5 +- .../CoverageResultTask.cs | 65 +++--- .../InstrumentationTask.cs | 15 +- src/coverlet.msbuild.tasks/MSBuildLogger.cs | 4 +- .../Properties/AssemblyInfo.cs | 3 + src/coverlet.msbuild.tasks/ReportWriter.cs | 5 +- .../AttachmentManagerTests.cs | 23 +- .../CoverletCoverageDataCollectorTests.cs | 40 ++-- .../CoverletSettingsParserTests.cs | 61 +++--- .../Properties/AssemblyInfo.cs | 3 + .../.editorconfig | 8 + .../.editorconfig | 8 + .../Coverage/CoverageSummaryTests.cs | 114 +++++----- .../Coverage/CoverageTests.AsyncAwait.cs | 14 +- .../CoverageTests.AsyncAwaitValueTask.cs | 5 +- .../Coverage/CoverageTests.AsyncForeach.cs | 6 +- .../Coverage/CoverageTests.AsyncIterator.cs | 6 +- .../Coverage/CoverageTests.AutoProps.cs | 5 +- .../Coverage/CoverageTests.AwaitUsing.cs | 5 +- .../Coverage/CoverageTests.CatchBlock.cs | 9 +- .../Coverage/CoverageTests.DoesNotReturn.cs | 5 +- ...erageTests.ExcludeFromCoverageAttribute.cs | 16 +- .../Coverage/CoverageTests.Filters.cs | 7 +- .../Coverage/CoverageTests.IntegerOverflow.cs | 13 +- .../Coverage/CoverageTests.Lambda.cs | 7 +- .../CoverageTests.SelectionStatements.cs | 7 +- .../Coverage/CoverageTests.Yield.cs | 16 +- .../Coverage/CoverageTests.cs | 22 +- .../Coverage/InstrumenterHelper.Assertions.cs | 26 +-- .../Coverage/InstrumenterHelper.cs | 23 +- .../CoverageResultTests.cs | 57 ++--- .../Helpers/FileSystemTests.cs | 6 +- .../Helpers/InstrumentationHelperTests.cs | 49 ++--- .../Helpers/RetryHelperTests.cs | 8 +- .../Helpers/SourceRootTranslatorTests.cs | 28 +-- .../InstrumenterResultTests.cs | 28 +-- .../Instrumentation/InstrumenterTests.cs | 167 ++++++++------- .../ModuleTrackerTemplateTests.cs | 19 +- .../Properties/AssemblyInfo.cs | 3 + .../Reporters/CoberturaReporterTests.cs | 62 +++--- .../Reporters/JsonReporterTests.cs | 17 +- .../Reporters/LcovReporterTests.cs | 20 +- .../Reporters/OpenCoverReporterTests.cs | 37 ++-- .../Reporters/ReporterFactoryTests.cs | 4 +- .../Reporters/Reporters.cs | 12 +- .../Reporters/TeamCityReporter.cs | 16 +- .../coverlet.core.tests/Samples/.editorconfig | 8 + .../Symbols/CecilSymbolHelperTests.cs | 182 ++++++++-------- .../.editorconfig | 8 + .../.editorconfig | 8 + .../AssertHelper.cs | 11 +- test/coverlet.integration.tests/BaseTest.cs | 31 +-- test/coverlet.integration.tests/Collectors.cs | 8 +- .../DeterministicBuild.cs | 8 +- test/coverlet.integration.tests/DotnetTool.cs | 6 +- test/coverlet.integration.tests/Msbuild.cs | 5 +- .../Properties/AssemblyInfo.cs | 3 + .../.editorconfig | 8 + .../.editorconfig | 8 + .../.editorconfig | 8 + .../ConditionalFact.cs | 6 +- .../Extensions.cs | 10 +- .../ITestCondition.cs | 5 +- .../Properties/AssemblyInfo.cs | 3 + .../SkipOnOS.cs | 5 +- test/coverlet.testsubject/.editorconfig | 8 + 135 files changed, 1709 insertions(+), 1161 deletions(-) create mode 100644 .editorconfig create mode 100644 src/coverlet.console/ConsoleTables/.editorconfig create mode 100644 test/coverlet.core.performancetest/.editorconfig create mode 100644 test/coverlet.core.tests.samples.netstandard/.editorconfig create mode 100644 test/coverlet.core.tests/Samples/.editorconfig create mode 100644 test/coverlet.integration.determisticbuild/.editorconfig create mode 100644 test/coverlet.integration.template/.editorconfig create mode 100644 test/coverlet.tests.projectsample.empty/.editorconfig create mode 100644 test/coverlet.tests.projectsample.excludedbyattribute/.editorconfig create mode 100644 test/coverlet.tests.projectsample.netframework/.editorconfig create mode 100644 test/coverlet.testsubject/.editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..26d6da3ab --- /dev/null +++ b/.editorconfig @@ -0,0 +1,197 @@ +# To learn more about .editorconfig see https://aka.ms/editorconfigdocs + +# top-most EditorConfig file +root = true + +############################### +# Core EditorConfig Options # +############################### +# All files +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 +charset = utf-8 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# YAML config files +[*.{yml,yaml}] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf +[*.{cmd,bat}] +end_of_line = crlf + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +insert_final_newline = true +charset = utf-8-bom +############################### +# .NET Coding Conventions # +############################### +[*.{cs,vb}] +# Organize usings +dotnet_sort_system_directives_first = true +## IDE0005: Using directive is unnecessary. +dotnet_diagnostic.IDE0005.severity = warning +# License header +file_header_template = Copyright (c) Toni Solarin-Sodara\nLicensed under the MIT license. See LICENSE file in the project root for full license information. +## IDE0073: The file header is missing or not located at the top of the file +dotnet_diagnostic.IDE0073.severity = warning +# this. preferences +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_readonly_field = true:warning +## IDE0044: Add readonly modifier +dotnet_diagnostic.IDE0044.severity = warning +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:warning +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +############################### +# Naming Conventions # +############################### +# Name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Static fields should have s_ prefix +dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected +dotnet_naming_style.static_prefix_style.required_prefix = s_ +dotnet_naming_style.static_prefix_style.capitalization = camel_case +# Internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case +############################### +# C# Coding Conventions # +############################### +[*.cs] +# Organize usings +csharp_using_directive_placement = outside_namespace:warning +# var preferences - use keywords instead of BCL types, and permit var only when the type is clear +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:warning +csharp_style_var_elsewhere = false:warning +# Expression-bodied members +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = true:warning +csharp_style_prefer_not_pattern = true +## IDE0083: Use pattern matching +dotnet_diagnostic.IDE0083.severity = warning +# Null-checking preferences +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning +# Expression-level preferences +csharp_prefer_braces = true:silent +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_prefer_simple_default_expression = true:warning +## IDE0034: Simplify 'default' expression +dotnet_diagnostic.IDE0034.severity = warning +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:warning +############################### +# C# Formatting Rules # +############################### +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +dotnet_style_allow_multiple_blank_lines_experimental=false:warning +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false +# Wrapping preferences +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true diff --git a/Directory.Build.props b/Directory.Build.props index 0e0ec9d3a..a075f6f8b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,8 +9,11 @@ true snupkg true + true + preview + true preview - $(NoWarn);NU5105 + $(NoWarn);NU5105 https://api.nuget.org/v3/index.json; diff --git a/coverlet.sln b/coverlet.sln index 34e7257db..b5e470431 100644 --- a/coverlet.sln +++ b/coverlet.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28902.138 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32208.508 MinimumVisualStudioVersion = 15.0.26124.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E877EBA4-E78B-4F7D-A2D3-1E070FED04CD}" EndProject @@ -27,6 +27,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.tests.projectsampl EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{77A15177-8262-488F-AF2B-91B9055715DA}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig .gitignore = .gitignore eng\azure-pipelines-nightly.yml = eng\azure-pipelines-nightly.yml eng\azure-pipelines.yml = eng\azure-pipelines.yml @@ -53,9 +54,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{9A8B19D4 test\Directory.Build.targets = test\Directory.Build.targets EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "coverlet.tests.projectsample.fsharp", "test\coverlet.tests.projectsample.fsharp\coverlet.tests.projectsample.fsharp.fsproj", "{1CBF6966-2A67-4D2C-8598-D174B83072F4}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "coverlet.tests.projectsample.fsharp", "test\coverlet.tests.projectsample.fsharp\coverlet.tests.projectsample.fsharp.fsproj", "{1CBF6966-2A67-4D2C-8598-D174B83072F4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "coverlet.tests.projectsample.netframework", "test\coverlet.tests.projectsample.netframework\coverlet.tests.projectsample.netframework.csproj", "{E69D68C9-78ED-4076-A14B-D07295A4B2A5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.tests.projectsample.netframework", "test\coverlet.tests.projectsample.netframework\coverlet.tests.projectsample.netframework.csproj", "{E69D68C9-78ED-4076-A14B-D07295A4B2A5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/coverlet.collector/DataCollection/AttachmentManager.cs b/src/coverlet.collector/DataCollection/AttachmentManager.cs index a7b2d24a0..8259f71f3 100644 --- a/src/coverlet.collector/DataCollection/AttachmentManager.cs +++ b/src/coverlet.collector/DataCollection/AttachmentManager.cs @@ -1,7 +1,9 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.ComponentModel; using System.IO; - using coverlet.collector.Resources; using Coverlet.Collector.Utilities; using Coverlet.Collector.Utilities.Interfaces; @@ -50,7 +52,7 @@ public AttachmentManager(DataCollectionSink dataSink, DataCollectionContext data _reportDirectory = Path.Combine(Path.GetTempPath(), reportDirectoryName); // Register events - _dataSink.SendFileCompleted += this.OnSendFileCompleted; + _dataSink.SendFileCompleted += OnSendFileCompleted; } /// @@ -61,10 +63,10 @@ public AttachmentManager(DataCollectionSink dataSink, DataCollectionContext data public void SendCoverageReport(string coverageReport, string coverageReportFileName) { // Save coverage report to file - string coverageReportPath = this.SaveCoverageReport(coverageReport, coverageReportFileName); + string coverageReportPath = SaveCoverageReport(coverageReport, coverageReportFileName); // Send coverage attachment to test platform. - this.SendAttachment(coverageReportPath); + SendAttachment(coverageReportPath); } /// @@ -78,9 +80,9 @@ public void Dispose() _countDownEvent.Wait(); if (_dataSink != null) { - _dataSink.SendFileCompleted -= this.OnSendFileCompleted; + _dataSink.SendFileCompleted -= OnSendFileCompleted; } - this.CleanupReportDirectory(); + CleanupReportDirectory(); } catch (Exception ex) { diff --git a/src/coverlet.collector/DataCollection/CoverageManager.cs b/src/coverlet.collector/DataCollection/CoverageManager.cs index ce12489f7..89ec41eb1 100644 --- a/src/coverlet.collector/DataCollection/CoverageManager.cs +++ b/src/coverlet.collector/DataCollection/CoverageManager.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -77,8 +80,8 @@ public void InstrumentModules() public IEnumerable<(string report, string fileName)> GetCoverageReports() { // Get coverage result - CoverageResult coverageResult = this.GetCoverageResult(); - return this.GetCoverageReports(coverageResult); + CoverageResult coverageResult = GetCoverageResult(); + return GetCoverageReports(coverageResult); } /// diff --git a/src/coverlet.collector/DataCollection/CoverageWrapper.cs b/src/coverlet.collector/DataCollection/CoverageWrapper.cs index 12f4005e7..9018ee387 100644 --- a/src/coverlet.collector/DataCollection/CoverageWrapper.cs +++ b/src/coverlet.collector/DataCollection/CoverageWrapper.cs @@ -1,4 +1,7 @@ -using Coverlet.Collector.Utilities.Interfaces; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Coverlet.Collector.Utilities.Interfaces; using Coverlet.Core; using Coverlet.Core.Abstractions; diff --git a/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs b/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs index d5094dc91..cccbd3d10 100644 --- a/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs +++ b/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -124,7 +127,7 @@ private void OnSessionStart(object sender, SessionStartEventArgs sessionStartEve try { // Get coverlet settings - IEnumerable testModules = this.GetTestModules(sessionStartEventArgs); + IEnumerable testModules = GetTestModules(sessionStartEventArgs); var coverletSettingsParser = new CoverletSettingsParser(_eqtTrace); CoverletSettings coverletSettings = coverletSettingsParser.Parse(_configurationElement, testModules); @@ -142,7 +145,7 @@ private void OnSessionStart(object sender, SessionStartEventArgs sessionStartEve catch (Exception ex) { _logger.LogWarning(ex.ToString()); - this.Dispose(true); + Dispose(true); } } @@ -179,7 +182,7 @@ private void OnSessionEnd(object sender, SessionEndEventArgs e) catch (Exception ex) { _logger.LogWarning(ex.ToString()); - this.Dispose(true); + Dispose(true); } } diff --git a/src/coverlet.collector/DataCollection/CoverletLogger.cs b/src/coverlet.collector/DataCollection/CoverletLogger.cs index 144d1ccf1..42eb6a1b2 100644 --- a/src/coverlet.collector/DataCollection/CoverletLogger.cs +++ b/src/coverlet.collector/DataCollection/CoverletLogger.cs @@ -1,5 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using Coverlet.Collector.Utilities; using Coverlet.Core.Abstractions; diff --git a/src/coverlet.collector/DataCollection/CoverletSettings.cs b/src/coverlet.collector/DataCollection/CoverletSettings.cs index 347173c76..bf04e6326 100644 --- a/src/coverlet.collector/DataCollection/CoverletSettings.cs +++ b/src/coverlet.collector/DataCollection/CoverletSettings.cs @@ -1,4 +1,7 @@ -using System.Linq; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Linq; using System.Text; namespace Coverlet.Collector.DataCollection diff --git a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs index 7fe778173..d18d1553d 100644 --- a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs +++ b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Xml; @@ -89,7 +92,7 @@ private string[] ParseReportFormats(XmlElement configurationElement) if (configurationElement != null) { XmlElement reportFormatElement = configurationElement[CoverletConstants.ReportFormatElementName]; - formats = this.SplitElement(reportFormatElement); + formats = SplitElement(reportFormatElement); } return formats is null || formats.Length == 0 ? new[] { CoverletConstants.DefaultReportFormat } : formats; @@ -103,7 +106,7 @@ private string[] ParseReportFormats(XmlElement configurationElement) private string[] ParseIncludeFilters(XmlElement configurationElement) { XmlElement includeFiltersElement = configurationElement[CoverletConstants.IncludeFiltersElementName]; - return this.SplitElement(includeFiltersElement); + return SplitElement(includeFiltersElement); } /// @@ -114,7 +117,7 @@ private string[] ParseIncludeFilters(XmlElement configurationElement) private string[] ParseIncludeDirectories(XmlElement configurationElement) { XmlElement includeDirectoriesElement = configurationElement[CoverletConstants.IncludeDirectoriesElementName]; - return this.SplitElement(includeDirectoriesElement); + return SplitElement(includeDirectoriesElement); } /// @@ -124,12 +127,12 @@ private string[] ParseIncludeDirectories(XmlElement configurationElement) /// Filters to exclude private string[] ParseExcludeFilters(XmlElement configurationElement) { - List excludeFilters = new List { CoverletConstants.DefaultExcludeFilter }; + var excludeFilters = new List { CoverletConstants.DefaultExcludeFilter }; if (configurationElement != null) { XmlElement excludeFiltersElement = configurationElement[CoverletConstants.ExcludeFiltersElementName]; - string[] filters = this.SplitElement(excludeFiltersElement); + string[] filters = SplitElement(excludeFiltersElement); if (filters != null) { excludeFilters.AddRange(filters); @@ -147,7 +150,7 @@ private string[] ParseExcludeFilters(XmlElement configurationElement) private string[] ParseExcludeSourceFiles(XmlElement configurationElement) { XmlElement excludeSourceFilesElement = configurationElement[CoverletConstants.ExcludeSourceFilesElementName]; - return this.SplitElement(excludeSourceFilesElement); + return SplitElement(excludeSourceFilesElement); } /// @@ -158,7 +161,7 @@ private string[] ParseExcludeSourceFiles(XmlElement configurationElement) private string[] ParseExcludeAttributes(XmlElement configurationElement) { XmlElement excludeAttributesElement = configurationElement[CoverletConstants.ExcludeAttributesElementName]; - return this.SplitElement(excludeAttributesElement); + return SplitElement(excludeAttributesElement); } /// @@ -240,7 +243,7 @@ private bool ParseSkipAutoProps(XmlElement configurationElement) private string[] ParseDoesNotReturnAttributes(XmlElement configurationElement) { XmlElement doesNotReturnAttributesElement = configurationElement[CoverletConstants.DoesNotReturnAttributesElementName]; - return this.SplitElement(doesNotReturnAttributesElement); + return SplitElement(doesNotReturnAttributesElement); } /// diff --git a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs index 5539d6b04..0ab4066a0 100644 --- a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs +++ b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs @@ -1,8 +1,10 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Diagnostics; using System.Reflection; using System.Text; - using coverlet.collector.Resources; using Coverlet.Collector.Utilities; using Coverlet.Core.Instrumentation; @@ -53,7 +55,7 @@ public void TestCaseStart(TestCaseStartArgs testCaseStartArgs) public void TestSessionEnd(TestSessionEndArgs testSessionEndArgs) { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { Type injectedInstrumentationClass = GetInstrumentationClass(assembly); if (injectedInstrumentationClass is null) @@ -64,7 +66,7 @@ public void TestSessionEnd(TestSessionEndArgs testSessionEndArgs) try { _eqtTrace.Verbose($"Calling ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'"); - var unloadModule = injectedInstrumentationClass.GetMethod(nameof(ModuleTrackerTemplate.UnloadModule), new[] { typeof(object), typeof(EventArgs) }); + MethodInfo unloadModule = injectedInstrumentationClass.GetMethod(nameof(ModuleTrackerTemplate.UnloadModule), new[] { typeof(object), typeof(EventArgs) }); unloadModule.Invoke(null, new[] { (object)this, EventArgs.Empty }); injectedInstrumentationClass.GetField("FlushHitFile", BindingFlags.Static | BindingFlags.Public).SetValue(null, false); _eqtTrace.Verbose($"Called ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'"); @@ -89,7 +91,7 @@ private Type GetInstrumentationClass(Assembly assembly) { try { - foreach (var type in assembly.GetTypes()) + foreach (Type type in assembly.GetTypes()) { if (type.Namespace == "Coverlet.Core.Instrumentation.Tracker" && type.Name.StartsWith(assembly.GetName().Name + "_")) @@ -104,7 +106,7 @@ private Type GetInstrumentationClass(Assembly assembly) { if (_enableExceptionLog) { - StringBuilder exceptionString = new StringBuilder(); + var exceptionString = new StringBuilder(); exceptionString.AppendFormat("{0}: Failed to get Instrumentation class for assembly '{1}' with error: {2}", CoverletConstants.InProcDataCollectorName, assembly, ex); exceptionString.AppendLine(); diff --git a/src/coverlet.collector/Properties/AssemblyInfo.cs b/src/coverlet.collector/Properties/AssemblyInfo.cs index 35079a9c9..4d4a63712 100644 --- a/src/coverlet.collector/Properties/AssemblyInfo.cs +++ b/src/coverlet.collector/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; using System.Runtime.CompilerServices; diff --git a/src/coverlet.collector/Utilities/CountDownEvent.cs b/src/coverlet.collector/Utilities/CountDownEvent.cs index a5a19b6f7..265c54103 100644 --- a/src/coverlet.collector/Utilities/CountDownEvent.cs +++ b/src/coverlet.collector/Utilities/CountDownEvent.cs @@ -1,6 +1,8 @@ -using System; -using System.Threading; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; +using System.Threading; using Coverlet.Collector.Utilities.Interfaces; namespace Coverlet.Collector.Utilities diff --git a/src/coverlet.collector/Utilities/CoverletConstants.cs b/src/coverlet.collector/Utilities/CoverletConstants.cs index 431beafc6..5aff53cfb 100644 --- a/src/coverlet.collector/Utilities/CoverletConstants.cs +++ b/src/coverlet.collector/Utilities/CoverletConstants.cs @@ -1,4 +1,7 @@ -namespace Coverlet.Collector.Utilities +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Coverlet.Collector.Utilities { internal static class CoverletConstants { diff --git a/src/coverlet.collector/Utilities/CoverletDataCollectorException.cs b/src/coverlet.collector/Utilities/CoverletDataCollectorException.cs index e0665673b..189b363f8 100644 --- a/src/coverlet.collector/Utilities/CoverletDataCollectorException.cs +++ b/src/coverlet.collector/Utilities/CoverletDataCollectorException.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Coverlet.Collector.Utilities { diff --git a/src/coverlet.collector/Utilities/DirectoryHelper.cs b/src/coverlet.collector/Utilities/DirectoryHelper.cs index d03d212cc..c9800a21b 100644 --- a/src/coverlet.collector/Utilities/DirectoryHelper.cs +++ b/src/coverlet.collector/Utilities/DirectoryHelper.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; using Coverlet.Collector.Utilities.Interfaces; namespace Coverlet.Collector.Utilities diff --git a/src/coverlet.collector/Utilities/FileHelper.cs b/src/coverlet.collector/Utilities/FileHelper.cs index f6e578380..f8a85b13e 100644 --- a/src/coverlet.collector/Utilities/FileHelper.cs +++ b/src/coverlet.collector/Utilities/FileHelper.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; using Coverlet.Collector.Utilities.Interfaces; namespace Coverlet.Collector.Utilities diff --git a/src/coverlet.collector/Utilities/Interfaces/ICountDown.cs b/src/coverlet.collector/Utilities/Interfaces/ICountDown.cs index 3c884b0bb..69eddbce4 100644 --- a/src/coverlet.collector/Utilities/Interfaces/ICountDown.cs +++ b/src/coverlet.collector/Utilities/Interfaces/ICountDown.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Coverlet.Collector.Utilities.Interfaces { diff --git a/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs b/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs index 1358fab1b..1a34612c0 100644 --- a/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs +++ b/src/coverlet.collector/Utilities/Interfaces/ICoverageWrapper.cs @@ -1,4 +1,7 @@ -using Coverlet.Collector.DataCollection; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Coverlet.Collector.DataCollection; using Coverlet.Core; using Coverlet.Core.Abstractions; diff --git a/src/coverlet.collector/Utilities/Interfaces/IDirectoryHelper.cs b/src/coverlet.collector/Utilities/Interfaces/IDirectoryHelper.cs index 8e26c0dcf..f148f21ea 100644 --- a/src/coverlet.collector/Utilities/Interfaces/IDirectoryHelper.cs +++ b/src/coverlet.collector/Utilities/Interfaces/IDirectoryHelper.cs @@ -1,4 +1,7 @@ -namespace Coverlet.Collector.Utilities.Interfaces +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Coverlet.Collector.Utilities.Interfaces { interface IDirectoryHelper { diff --git a/src/coverlet.collector/Utilities/Interfaces/IFileHelper.cs b/src/coverlet.collector/Utilities/Interfaces/IFileHelper.cs index 8fd0ab9ea..1ddcc8678 100644 --- a/src/coverlet.collector/Utilities/Interfaces/IFileHelper.cs +++ b/src/coverlet.collector/Utilities/Interfaces/IFileHelper.cs @@ -1,4 +1,7 @@ -namespace Coverlet.Collector.Utilities.Interfaces +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Coverlet.Collector.Utilities.Interfaces { internal interface IFileHelper { diff --git a/src/coverlet.collector/Utilities/TestPlatformEqtTrace.cs b/src/coverlet.collector/Utilities/TestPlatformEqtTrace.cs index 31f5d4409..7c02f6d03 100644 --- a/src/coverlet.collector/Utilities/TestPlatformEqtTrace.cs +++ b/src/coverlet.collector/Utilities/TestPlatformEqtTrace.cs @@ -1,4 +1,7 @@ -using Microsoft.VisualStudio.TestPlatform.ObjectModel; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.VisualStudio.TestPlatform.ObjectModel; namespace Coverlet.Collector.Utilities { diff --git a/src/coverlet.collector/Utilities/TestPlatformLogger.cs b/src/coverlet.collector/Utilities/TestPlatformLogger.cs index 47f55c897..105e4c9d9 100644 --- a/src/coverlet.collector/Utilities/TestPlatformLogger.cs +++ b/src/coverlet.collector/Utilities/TestPlatformLogger.cs @@ -1,4 +1,7 @@ -using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; namespace Coverlet.Collector.Utilities { diff --git a/src/coverlet.console/ConsoleTables/.editorconfig b/src/coverlet.console/ConsoleTables/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/src/coverlet.console/ConsoleTables/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/src/coverlet.console/ExitCodes.cs b/src/coverlet.console/ExitCodes.cs index 2677b3f19..670eda89a 100644 --- a/src/coverlet.console/ExitCodes.cs +++ b/src/coverlet.console/ExitCodes.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; /// /// Exit Codes returned from Coverlet console process. diff --git a/src/coverlet.console/Logging/ConsoleLogger.cs b/src/coverlet.console/Logging/ConsoleLogger.cs index 98e620f16..1752ddc43 100644 --- a/src/coverlet.console/Logging/ConsoleLogger.cs +++ b/src/coverlet.console/Logging/ConsoleLogger.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using Coverlet.Core.Abstractions; using static System.Console; @@ -39,4 +42,4 @@ private void Log(LogLevel level, string message, ConsoleColor color) } } } -} \ No newline at end of file +} diff --git a/src/coverlet.console/Logging/LogLevel.cs b/src/coverlet.console/Logging/LogLevel.cs index 5ec47ef90..2e0cf7320 100644 --- a/src/coverlet.console/Logging/LogLevel.cs +++ b/src/coverlet.console/Logging/LogLevel.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + namespace Coverlet.Console.Logging { /// diff --git a/src/coverlet.console/Program.cs b/src/coverlet.console/Program.cs index ae3b02d03..25f5f7350 100644 --- a/src/coverlet.console/Program.cs +++ b/src/coverlet.console/Program.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -6,7 +9,6 @@ using System.IO; using System.Linq; using System.Text; - using ConsoleTables; using Coverlet.Console.Logging; using Coverlet.Core; @@ -37,7 +39,7 @@ static int Main(string[] args) ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); var logger = (ConsoleLogger)serviceProvider.GetService(); - var fileSystem = serviceProvider.GetService(); + IFileSystem fileSystem = serviceProvider.GetService(); var app = new CommandLineApplication { @@ -134,15 +136,15 @@ static int Main(string[] args) process.WaitForExit(); - var dOutput = output.HasValue() ? output.Value() : Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar.ToString(); - var dThresholdTypes = thresholdTypes.HasValue() ? thresholdTypes.Values : new List(new string[] { "line", "branch", "method" }); - var dThresholdStat = thresholdStat.HasValue() ? Enum.Parse(thresholdStat.Value(), true) : Enum.Parse("minimum", true); + string dOutput = output.HasValue() ? output.Value() : Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar.ToString(); + List dThresholdTypes = thresholdTypes.HasValue() ? thresholdTypes.Values : new List(new string[] { "line", "branch", "method" }); + ThresholdStatistic dThresholdStat = thresholdStat.HasValue() ? Enum.Parse(thresholdStat.Value(), true) : Enum.Parse("minimum", true); logger.LogInformation("\nCalculating coverage result..."); - var result = coverage.GetCoverageResult(); - - var directory = Path.GetDirectoryName(dOutput); + CoverageResult result = coverage.GetCoverageResult(); + + string directory = Path.GetDirectoryName(dOutput); if (directory == string.Empty) { directory = Directory.GetCurrentDirectory(); @@ -152,9 +154,9 @@ static int Main(string[] args) Directory.CreateDirectory(directory); } - foreach (var format in formats.HasValue() ? formats.Values : new List(new string[] { "json" })) + foreach (string format in formats.HasValue() ? formats.Values : new List(new string[] { "json" })) { - var reporter = new ReporterFactory(format).CreateReporter(); + Core.Abstractions.IReporter reporter = new ReporterFactory(format).CreateReporter(); if (reporter == null) { throw new Exception($"Specified output format '{format}' is not supported"); @@ -169,19 +171,19 @@ static int Main(string[] args) else { // Output to file - var filename = Path.GetFileName(dOutput); + string filename = Path.GetFileName(dOutput); filename = (filename == string.Empty) ? $"coverage.{reporter.Extension}" : filename; filename = Path.HasExtension(filename) ? filename : $"{filename}.{reporter.Extension}"; - var report = Path.Combine(directory, filename); + string report = Path.Combine(directory, filename); logger.LogInformation($" Generating report '{report}'", important: true); fileSystem.WriteAllText(report, reporter.Report(result, sourceRootTranslator)); } } var thresholdTypeFlagQueue = new Queue(); - - foreach (var thresholdType in dThresholdTypes) + + foreach (string thresholdType in dThresholdTypes) { if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase)) { @@ -196,19 +198,19 @@ static int Main(string[] args) thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Method); } } - - Dictionary thresholdTypeFlagValues = new Dictionary(); + + var thresholdTypeFlagValues = new Dictionary(); if (threshold.HasValue() && threshold.Value().Contains(',')) { - var thresholdValues = threshold.Value().Split(',', StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()); - if (thresholdValues.Count() != thresholdTypeFlagQueue.Count()) + IEnumerable thresholdValues = threshold.Value().Split(',', StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()); + if (thresholdValues.Count() != thresholdTypeFlagQueue.Count) { - throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count()}) and values count ({thresholdValues.Count()}) doesn't match"); + throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count}) and values count ({thresholdValues.Count()}) doesn't match"); } - foreach (var thresholdValue in thresholdValues) + foreach (string thresholdValue in thresholdValues) { - if (double.TryParse(thresholdValue, out var value)) + if (double.TryParse(thresholdValue, out double value)) { thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = value; } @@ -231,23 +233,23 @@ static int Main(string[] args) var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method"); var summary = new CoverageSummary(); - var linePercentCalculation = summary.CalculateLineCoverage(result.Modules); - var branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); - var methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); + CoverageDetails linePercentCalculation = summary.CalculateLineCoverage(result.Modules); + CoverageDetails branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); + CoverageDetails methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); - var totalLinePercent = linePercentCalculation.Percent; - var totalBranchPercent = branchPercentCalculation.Percent; - var totalMethodPercent = methodPercentCalculation.Percent; + double totalLinePercent = linePercentCalculation.Percent; + double totalBranchPercent = branchPercentCalculation.Percent; + double totalMethodPercent = methodPercentCalculation.Percent; - var averageLinePercent = linePercentCalculation.AverageModulePercent; - var averageBranchPercent = branchPercentCalculation.AverageModulePercent; - var averageMethodPercent = methodPercentCalculation.AverageModulePercent; + double averageLinePercent = linePercentCalculation.AverageModulePercent; + double averageBranchPercent = branchPercentCalculation.AverageModulePercent; + double averageMethodPercent = methodPercentCalculation.AverageModulePercent; - foreach (var _module in result.Modules) + foreach (KeyValuePair _module in result.Modules) { - var linePercent = summary.CalculateLineCoverage(_module.Value).Percent; - var branchPercent = summary.CalculateBranchCoverage(_module.Value).Percent; - var methodPercent = summary.CalculateMethodCoverage(_module.Value).Percent; + double linePercent = summary.CalculateLineCoverage(_module.Value).Percent; + double branchPercent = summary.CalculateBranchCoverage(_module.Value).Percent; + double methodPercent = summary.CalculateMethodCoverage(_module.Value).Percent; coverageTable.AddRow(Path.GetFileNameWithoutExtension(_module.Key), $"{InvariantFormat(linePercent)}%", $"{InvariantFormat(branchPercent)}%", $"{InvariantFormat(methodPercent)}%"); } @@ -266,15 +268,15 @@ static int Main(string[] args) { exitCode += (int)CommandExitCodes.TestFailed; } - - var thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, dThresholdStat); + + ThresholdTypeFlags thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, dThresholdStat); if (thresholdTypeFlags != ThresholdTypeFlags.None) { exitCode += (int)CommandExitCodes.CoverageBelowThreshold; var exceptionMessageBuilder = new StringBuilder(); if ((thresholdTypeFlags & ThresholdTypeFlags.Line) != ThresholdTypeFlags.None) { - exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} line coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Line]}"); + exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} line coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Line]}"); } if ((thresholdTypeFlags & ThresholdTypeFlags.Branch) != ThresholdTypeFlags.None) @@ -284,7 +286,7 @@ static int Main(string[] args) if ((thresholdTypeFlags & ThresholdTypeFlags.Method) != ThresholdTypeFlags.None) { - exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} method coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Method]}"); + exceptionMessageBuilder.AppendLine($"The {dThresholdStat.ToString().ToLower()} method coverage is below the specified {thresholdTypeFlagValues[ThresholdTypeFlags.Method]}"); } throw new Exception(exceptionMessageBuilder.ToString()); } diff --git a/src/coverlet.console/Properties/AssemblyInfo.cs b/src/coverlet.console/Properties/AssemblyInfo.cs index 27cbf8a13..59db2a82f 100644 --- a/src/coverlet.console/Properties/AssemblyInfo.cs +++ b/src/coverlet.console/Properties/AssemblyInfo.cs @@ -1 +1,4 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + [assembly: System.Reflection.AssemblyKeyFileAttribute("coverlet.console.snk")] \ No newline at end of file diff --git a/src/coverlet.core/Abstractions/ICecilSymbolHelper.cs b/src/coverlet.core/Abstractions/ICecilSymbolHelper.cs index 10bf1719a..06cdde3d1 100644 --- a/src/coverlet.core/Abstractions/ICecilSymbolHelper.cs +++ b/src/coverlet.core/Abstractions/ICecilSymbolHelper.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; using Coverlet.Core.Symbols; using Mono.Cecil; using Mono.Cecil.Cil; diff --git a/src/coverlet.core/Abstractions/IConsole.cs b/src/coverlet.core/Abstractions/IConsole.cs index 9bc7e4e0b..72991cac5 100644 --- a/src/coverlet.core/Abstractions/IConsole.cs +++ b/src/coverlet.core/Abstractions/IConsole.cs @@ -1,4 +1,7 @@ -namespace Coverlet.Core.Abstractions +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Coverlet.Core.Abstractions { internal interface IConsole { diff --git a/src/coverlet.core/Abstractions/IFileSystem.cs b/src/coverlet.core/Abstractions/IFileSystem.cs index 54185dbf5..cb710c758 100644 --- a/src/coverlet.core/Abstractions/IFileSystem.cs +++ b/src/coverlet.core/Abstractions/IFileSystem.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; namespace Coverlet.Core.Abstractions { diff --git a/src/coverlet.core/Abstractions/IInstrumentationHelper.cs b/src/coverlet.core/Abstractions/IInstrumentationHelper.cs index 295a111d1..ed41dcce0 100644 --- a/src/coverlet.core/Abstractions/IInstrumentationHelper.cs +++ b/src/coverlet.core/Abstractions/IInstrumentationHelper.cs @@ -1,4 +1,7 @@ -namespace Coverlet.Core.Abstractions +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Coverlet.Core.Abstractions { internal interface IInstrumentationHelper { diff --git a/src/coverlet.core/Abstractions/ILogger.cs b/src/coverlet.core/Abstractions/ILogger.cs index bc7e78c01..c3e6ef15e 100644 --- a/src/coverlet.core/Abstractions/ILogger.cs +++ b/src/coverlet.core/Abstractions/ILogger.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; namespace Coverlet.Core.Abstractions diff --git a/src/coverlet.core/Abstractions/IProcessExitHandler.cs b/src/coverlet.core/Abstractions/IProcessExitHandler.cs index fc5262d89..635015946 100644 --- a/src/coverlet.core/Abstractions/IProcessExitHandler.cs +++ b/src/coverlet.core/Abstractions/IProcessExitHandler.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Coverlet.Core.Abstractions { diff --git a/src/coverlet.core/Abstractions/IReporter.cs b/src/coverlet.core/Abstractions/IReporter.cs index 5a76d1858..9e497d62a 100644 --- a/src/coverlet.core/Abstractions/IReporter.cs +++ b/src/coverlet.core/Abstractions/IReporter.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + namespace Coverlet.Core.Abstractions { internal interface IReporter diff --git a/src/coverlet.core/Abstractions/IRetryHelper.cs b/src/coverlet.core/Abstractions/IRetryHelper.cs index c0e6e14cb..88a1b29d5 100644 --- a/src/coverlet.core/Abstractions/IRetryHelper.cs +++ b/src/coverlet.core/Abstractions/IRetryHelper.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Coverlet.Core.Abstractions { diff --git a/src/coverlet.core/Abstractions/ISourceRootTranslator.cs b/src/coverlet.core/Abstractions/ISourceRootTranslator.cs index c91077950..f64907b7d 100644 --- a/src/coverlet.core/Abstractions/ISourceRootTranslator.cs +++ b/src/coverlet.core/Abstractions/ISourceRootTranslator.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; using Coverlet.Core.Helpers; namespace Coverlet.Core.Abstractions diff --git a/src/coverlet.core/Attributes/DoesNotReturnAttribute.cs b/src/coverlet.core/Attributes/DoesNotReturnAttribute.cs index a35be1336..cebe198f1 100644 --- a/src/coverlet.core/Attributes/DoesNotReturnAttribute.cs +++ b/src/coverlet.core/Attributes/DoesNotReturnAttribute.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Coverlet.Core.Attributes { diff --git a/src/coverlet.core/Attributes/ExcludeFromCoverage.cs b/src/coverlet.core/Attributes/ExcludeFromCoverage.cs index f7281ca04..71efcb7bc 100644 --- a/src/coverlet.core/Attributes/ExcludeFromCoverage.cs +++ b/src/coverlet.core/Attributes/ExcludeFromCoverage.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; namespace Coverlet.Core.Attributes diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs index 30714c0dd..ecd9a834d 100644 --- a/src/coverlet.core/Coverage.cs +++ b/src/coverlet.core/Coverage.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.IO; @@ -6,7 +9,6 @@ using Coverlet.Core.Abstractions; using Coverlet.Core.Helpers; using Coverlet.Core.Instrumentation; - using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -45,20 +47,16 @@ internal class CoverageParameters internal class Coverage { - private string _moduleOrAppDirectory; - private string _identifier; - private ILogger _logger; - private IInstrumentationHelper _instrumentationHelper; - private IFileSystem _fileSystem; - private ISourceRootTranslator _sourceRootTranslator; - private ICecilSymbolHelper _cecilSymbolHelper; - private List _results; - private CoverageParameters _parameters; - - public string Identifier - { - get { return _identifier; } - } + private readonly string _moduleOrAppDirectory; + private readonly ILogger _logger; + private readonly IInstrumentationHelper _instrumentationHelper; + private readonly IFileSystem _fileSystem; + private readonly ISourceRootTranslator _sourceRootTranslator; + private readonly ICecilSymbolHelper _cecilSymbolHelper; + private readonly List _results; + private readonly CoverageParameters _parameters; + + public string Identifier { get; } public Coverage(string moduleOrDirectory, CoverageParameters parameters, @@ -76,7 +74,7 @@ public Coverage(string moduleOrDirectory, _fileSystem = fileSystem; _sourceRootTranslator = sourceRootTranslator; _cecilSymbolHelper = cecilSymbolHelper; - _identifier = Guid.NewGuid().ToString(); + Identifier = Guid.NewGuid().ToString(); _results = new List(); } @@ -86,7 +84,7 @@ public Coverage(CoveragePrepareResult prepareResult, IFileSystem fileSystem, ISourceRootTranslator sourceRootTranslator) { - _identifier = prepareResult.Identifier; + Identifier = prepareResult.Identifier; _moduleOrAppDirectory = prepareResult.ModuleOrDirectory; _parameters = prepareResult.Parameters; _results = new List(prepareResult.Results); @@ -107,7 +105,7 @@ public CoveragePrepareResult PrepareModules() _parameters.ExcludeFilters = _parameters.ExcludeFilters?.Where(f => _instrumentationHelper.IsValidFilterExpression(f)).ToArray(); _parameters.IncludeFilters = _parameters.IncludeFilters?.Where(f => _instrumentationHelper.IsValidFilterExpression(f)).ToArray(); - foreach (var module in modules) + foreach (string module in modules) { if (_instrumentationHelper.IsModuleExcluded(module, _parameters.ExcludeFilters) || !_instrumentationHelper.IsModuleIncluded(module, _parameters.IncludeFilters)) @@ -117,7 +115,7 @@ public CoveragePrepareResult PrepareModules() } var instrumenter = new Instrumenter(module, - _identifier, + Identifier, _parameters, _logger, _instrumentationHelper, @@ -127,7 +125,7 @@ public CoveragePrepareResult PrepareModules() if (instrumenter.CanInstrument()) { - _instrumentationHelper.BackupOriginalModule(module, _identifier); + _instrumentationHelper.BackupOriginalModule(module, Identifier); // Guard code path and restore if instrumentation fails. try @@ -142,14 +140,14 @@ public CoveragePrepareResult PrepareModules() catch (Exception ex) { _logger.LogWarning($"Unable to instrument module: {module}\n{ex}"); - _instrumentationHelper.RestoreOriginalModule(module, _identifier); + _instrumentationHelper.RestoreOriginalModule(module, Identifier); } } } return new CoveragePrepareResult() { - Identifier = _identifier, + Identifier = Identifier, ModuleOrDirectory = _moduleOrAppDirectory, Parameters = _parameters, Results = _results.ToArray() @@ -160,14 +158,14 @@ public CoverageResult GetCoverageResult() { CalculateCoverage(); - Modules modules = new Modules(); - foreach (var result in _results) + var modules = new Modules(); + foreach (InstrumenterResult result in _results) { - Documents documents = new Documents(); - foreach (var doc in result.Documents.Values) + var documents = new Documents(); + foreach (Document doc in result.Documents.Values) { // Construct Line Results - foreach (var line in doc.Lines.Values) + foreach (Line line in doc.Lines.Values) { if (documents.TryGetValue(doc.Path, out Classes classes)) { @@ -200,7 +198,7 @@ public CoverageResult GetCoverageResult() } // Construct Branch Results - foreach (var branch in doc.Branches.Values) + foreach (Branch branch in doc.Branches.Values) { if (documents.TryGetValue(doc.Path, out Classes classes)) { @@ -242,7 +240,7 @@ public CoverageResult GetCoverageResult() } modules.Add(Path.GetFileName(result.ModulePath), documents); - _instrumentationHelper.RestoreOriginalModule(result.ModulePath, _identifier); + _instrumentationHelper.RestoreOriginalModule(result.ModulePath, Identifier); } // In case of anonymous delegate compiler generate a custom class and passes it as type.method delegate. @@ -250,11 +248,11 @@ public CoverageResult GetCoverageResult() // We search "method" with same "Line" of closure class method and add missing branches to it, // in this way we correctly report missing branch inside compiled generated anonymous delegate. List compileGeneratedClassToRemove = null; - foreach (var module in modules) + foreach (KeyValuePair module in modules) { - foreach (var document in module.Value) + foreach (KeyValuePair document in module.Value) { - foreach (var @class in document.Value) + foreach (KeyValuePair @class in document.Value) { // We fix only lamda generated class // https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNameKind.cs#L18 @@ -263,9 +261,9 @@ public CoverageResult GetCoverageResult() continue; } - foreach (var method in @class.Value) + foreach (KeyValuePair method in @class.Value) { - foreach (var branch in method.Value.Branches) + foreach (BranchInfo branch in method.Value.Branches) { if (BranchInCompilerGeneratedClass(method.Key)) { @@ -295,13 +293,13 @@ public CoverageResult GetCoverageResult() } // After method/branches analysis of compiled generated class we can remove noise from reports - if (!(compileGeneratedClassToRemove is null)) + if (compileGeneratedClassToRemove is not null) { - foreach (var module in modules) + foreach (KeyValuePair module in modules) { - foreach (var document in module.Value) + foreach (KeyValuePair document in module.Value) { - foreach (var classToRemove in compileGeneratedClassToRemove) + foreach (string classToRemove in compileGeneratedClassToRemove) { document.Value.Remove(classToRemove); } @@ -309,7 +307,7 @@ public CoverageResult GetCoverageResult() } } - var coverageResult = new CoverageResult { Identifier = _identifier, Modules = modules, InstrumentedResults = _results, Parameters = _parameters }; + var coverageResult = new CoverageResult { Identifier = Identifier, Modules = modules, InstrumentedResults = _results, Parameters = _parameters }; if (!string.IsNullOrEmpty(_parameters.MergeWith) && !string.IsNullOrWhiteSpace(_parameters.MergeWith) && _fileSystem.Exists(_parameters.MergeWith)) { @@ -322,7 +320,7 @@ public CoverageResult GetCoverageResult() private bool BranchInCompilerGeneratedClass(string methodName) { - foreach (var instrumentedResult in _results) + foreach (InstrumenterResult instrumentedResult in _results) { if (instrumentedResult.BranchesInCompiledGeneratedClass.Contains(methodName)) { @@ -334,16 +332,16 @@ private bool BranchInCompilerGeneratedClass(string methodName) private Method GetMethodWithSameLineInSameDocument(Classes documentClasses, string compilerGeneratedClassName, int branchLine) { - foreach (var @class in documentClasses) + foreach (KeyValuePair @class in documentClasses) { if (@class.Key == compilerGeneratedClassName) { continue; } - foreach (var method in @class.Value) + foreach (KeyValuePair method in @class.Value) { - foreach (var line in method.Value.Lines) + foreach (KeyValuePair line in method.Value.Lines) { if (line.Key == branchLine) { @@ -357,7 +355,7 @@ private Method GetMethodWithSameLineInSameDocument(Classes documentClasses, stri private void CalculateCoverage() { - foreach (var result in _results) + foreach (InstrumenterResult result in _results) { if (!_fileSystem.Exists(result.HitsFilePath)) { @@ -369,12 +367,12 @@ private void CalculateCoverage() continue; } - List documents = result.Documents.Values.ToList(); + var documents = result.Documents.Values.ToList(); if (_parameters.UseSourceLink && result.SourceLink != null) { - var jObject = JObject.Parse(result.SourceLink)["documents"]; - var sourceLinkDocuments = JsonConvert.DeserializeObject>(jObject.ToString()); - foreach (var document in documents) + JToken jObject = JObject.Parse(result.SourceLink)["documents"]; + Dictionary sourceLinkDocuments = JsonConvert.DeserializeObject>(jObject.ToString()); + foreach (Document document in documents) { document.Path = GetSourceLinkUrl(sourceLinkDocuments, document.Path); } @@ -408,7 +406,7 @@ private void CalculateCoverage() } var documentsList = result.Documents.Values.ToList(); - using (var fs = _fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open, FileAccess.Read)) + using (Stream fs = _fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open, FileAccess.Read)) using (var br = new BinaryReader(fs)) { int hitCandidatesCount = br.ReadInt32(); @@ -417,8 +415,8 @@ private void CalculateCoverage() for (int i = 0; i < hitCandidatesCount; ++i) { - var hitLocation = result.HitCandidates[i]; - var document = documentsList[hitLocation.docIndex]; + HitCandidate hitLocation = result.HitCandidates[i]; + Document document = documentsList[hitLocation.docIndex]; int hits = br.ReadInt32(); if (hits == 0) @@ -428,7 +426,7 @@ private void CalculateCoverage() if (hitLocation.isBranch) { - var branch = document.Branches[new BranchKey(hitLocation.start, hitLocation.end)]; + Branch branch = document.Branches[new BranchKey(hitLocation.start, hitLocation.end)]; branch.Hits += hits; if (branch.Hits < 0) @@ -443,7 +441,7 @@ private void CalculateCoverage() continue; } - var line = document.Lines[j]; + Line line = document.Lines[j]; line.Hits += hits; if (line.Hits < 0) @@ -472,10 +470,10 @@ private string GetSourceLinkUrl(Dictionary sourceLinkDocuments, return url; } - var keyWithBestMatch = string.Empty; - var relativePathOfBestMatch = string.Empty; + string keyWithBestMatch = string.Empty; + string relativePathOfBestMatch = string.Empty; - foreach (var sourceLinkDocument in sourceLinkDocuments) + foreach (KeyValuePair sourceLinkDocument in sourceLinkDocuments) { string key = sourceLinkDocument.Key; if (Path.GetFileName(key) != "*") continue; diff --git a/src/coverlet.core/CoverageDetails.cs b/src/coverlet.core/CoverageDetails.cs index be2ccd4e2..59db863c2 100644 --- a/src/coverlet.core/CoverageDetails.cs +++ b/src/coverlet.core/CoverageDetails.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; namespace Coverlet.Core diff --git a/src/coverlet.core/CoveragePrepareResult.cs b/src/coverlet.core/CoveragePrepareResult.cs index 9bf9037f8..7c15d76c3 100644 --- a/src/coverlet.core/CoveragePrepareResult.cs +++ b/src/coverlet.core/CoveragePrepareResult.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; using System.Runtime.Serialization; using Coverlet.Core.Instrumentation; @@ -30,7 +33,7 @@ public static CoveragePrepareResult Deserialize(Stream serializedInstrumentState public static Stream Serialize(CoveragePrepareResult instrumentState) { - MemoryStream ms = new MemoryStream(); + var ms = new MemoryStream(); new DataContractSerializer(typeof(CoveragePrepareResult)).WriteObject(ms, instrumentState); ms.Position = 0; return ms; diff --git a/src/coverlet.core/CoverageResult.cs b/src/coverlet.core/CoverageResult.cs index e02e5e0f5..4e981346b 100644 --- a/src/coverlet.core/CoverageResult.cs +++ b/src/coverlet.core/CoverageResult.cs @@ -1,10 +1,10 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Collections.Generic; -using System.IO; using System.Linq; using Coverlet.Core.Enums; using Coverlet.Core.Instrumentation; -using Coverlet.Core.Symbols; namespace Coverlet.Core { @@ -48,54 +48,54 @@ public CoverageResult() { } public void Merge(Modules modules) { - foreach (var module in modules) + foreach (KeyValuePair module in modules) { - if (!this.Modules.Keys.Contains(module.Key)) + if (!Modules.Keys.Contains(module.Key)) { - this.Modules.Add(module.Key, module.Value); + Modules.Add(module.Key, module.Value); } else { - foreach (var document in module.Value) + foreach (KeyValuePair document in module.Value) { - if (!this.Modules[module.Key].ContainsKey(document.Key)) + if (!Modules[module.Key].ContainsKey(document.Key)) { - this.Modules[module.Key].Add(document.Key, document.Value); + Modules[module.Key].Add(document.Key, document.Value); } else { - foreach (var @class in document.Value) + foreach (KeyValuePair @class in document.Value) { - if (!this.Modules[module.Key][document.Key].ContainsKey(@class.Key)) + if (!Modules[module.Key][document.Key].ContainsKey(@class.Key)) { - this.Modules[module.Key][document.Key].Add(@class.Key, @class.Value); + Modules[module.Key][document.Key].Add(@class.Key, @class.Value); } else { - foreach (var method in @class.Value) + foreach (KeyValuePair method in @class.Value) { - if (!this.Modules[module.Key][document.Key][@class.Key].ContainsKey(method.Key)) + if (!Modules[module.Key][document.Key][@class.Key].ContainsKey(method.Key)) { - this.Modules[module.Key][document.Key][@class.Key].Add(method.Key, method.Value); + Modules[module.Key][document.Key][@class.Key].Add(method.Key, method.Value); } else { - foreach (var line in method.Value.Lines) + foreach (KeyValuePair line in method.Value.Lines) { - if (!this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.ContainsKey(line.Key)) + if (!Modules[module.Key][document.Key][@class.Key][method.Key].Lines.ContainsKey(line.Key)) { - this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines.Add(line.Key, line.Value); + Modules[module.Key][document.Key][@class.Key][method.Key].Lines.Add(line.Key, line.Value); } else { - this.Modules[module.Key][document.Key][@class.Key][method.Key].Lines[line.Key] += line.Value; + Modules[module.Key][document.Key][@class.Key][method.Key].Lines[line.Key] += line.Value; } } - foreach (var branch in method.Value.Branches) + foreach (BranchInfo branch in method.Value.Branches) { - var branches = this.Modules[module.Key][document.Key][@class.Key][method.Key].Branches; - var branchInfo = branches.FirstOrDefault(b => b.EndOffset == branch.EndOffset && b.Line == branch.Line && b.Offset == branch.Offset && b.Ordinal == branch.Ordinal && b.Path == branch.Path); + Branches branches = Modules[module.Key][document.Key][@class.Key][method.Key].Branches; + BranchInfo branchInfo = branches.FirstOrDefault(b => b.EndOffset == branch.EndOffset && b.Line == branch.Line && b.Offset == branch.Offset && b.Ordinal == branch.Ordinal && b.Path == branch.Path); if (branchInfo == null) branches.Add(branch); else @@ -113,7 +113,7 @@ public void Merge(Modules modules) public ThresholdTypeFlags GetThresholdTypesBelowThreshold(CoverageSummary summary, Dictionary thresholdTypeFlagValues, ThresholdStatistic thresholdStat) { - var thresholdTypeFlags = ThresholdTypeFlags.None; + ThresholdTypeFlags thresholdTypeFlags = ThresholdTypeFlags.None; switch (thresholdStat) { case ThresholdStatistic.Minimum: @@ -121,7 +121,7 @@ public ThresholdTypeFlags GetThresholdTypesBelowThreshold(CoverageSummary summar if (!Modules.Any()) thresholdTypeFlags = CompareThresholdValues(thresholdTypeFlagValues, thresholdTypeFlags, 0, 0, 0); - foreach (var module in Modules) + foreach (KeyValuePair module in Modules) { double line = summary.CalculateLineCoverage(module.Value).Percent; double branch = summary.CalculateBranchCoverage(module.Value).Percent; @@ -158,19 +158,19 @@ private static ThresholdTypeFlags CompareThresholdValues( Dictionary thresholdTypeFlagValues, ThresholdTypeFlags thresholdTypeFlags, double line, double branch, double method) { - if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Line, out var lineThresholdValue) && + if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Line, out double lineThresholdValue) && lineThresholdValue > line) { thresholdTypeFlags |= ThresholdTypeFlags.Line; } - if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Branch, out var branchThresholdValue) && + if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Branch, out double branchThresholdValue) && branchThresholdValue > branch) { thresholdTypeFlags |= ThresholdTypeFlags.Branch; } - if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Method, out var methodThresholdValue) && + if (thresholdTypeFlagValues.TryGetValue(ThresholdTypeFlags.Method, out double methodThresholdValue) && methodThresholdValue > method) { thresholdTypeFlags |= ThresholdTypeFlags.Method; @@ -179,4 +179,4 @@ private static ThresholdTypeFlags CompareThresholdValues( return thresholdTypeFlags; } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/CoverageSummary.cs b/src/coverlet.core/CoverageSummary.cs index 19700deac..a56cda454 100644 --- a/src/coverlet.core/CoverageSummary.cs +++ b/src/coverlet.core/CoverageSummary.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Linq; @@ -17,9 +20,9 @@ public CoverageDetails CalculateLineCoverage(Lines lines) public CoverageDetails CalculateLineCoverage(Methods methods) { var details = new CoverageDetails(); - foreach (var method in methods) + foreach (KeyValuePair method in methods) { - var methodCoverage = CalculateLineCoverage(method.Value.Lines); + CoverageDetails methodCoverage = CalculateLineCoverage(method.Value.Lines); details.Covered += methodCoverage.Covered; details.Total += methodCoverage.Total; } @@ -29,9 +32,9 @@ public CoverageDetails CalculateLineCoverage(Methods methods) public CoverageDetails CalculateLineCoverage(Classes classes) { var details = new CoverageDetails(); - foreach (var @class in classes) + foreach (KeyValuePair @class in classes) { - var classCoverage = CalculateLineCoverage(@class.Value); + CoverageDetails classCoverage = CalculateLineCoverage(@class.Value); details.Covered += classCoverage.Covered; details.Total += classCoverage.Total; } @@ -41,9 +44,9 @@ public CoverageDetails CalculateLineCoverage(Classes classes) public CoverageDetails CalculateLineCoverage(Documents documents) { var details = new CoverageDetails(); - foreach (var document in documents) + foreach (KeyValuePair document in documents) { - var documentCoverage = CalculateLineCoverage(document.Value); + CoverageDetails documentCoverage = CalculateLineCoverage(document.Value); details.Covered += documentCoverage.Covered; details.Total += documentCoverage.Total; } @@ -52,15 +55,15 @@ public CoverageDetails CalculateLineCoverage(Documents documents) public CoverageDetails CalculateLineCoverage(Modules modules) { - var details = new CoverageDetails{Modules = modules}; - var accumPercent = 0.0D; + var details = new CoverageDetails { Modules = modules }; + double accumPercent = 0.0D; if (modules.Count == 0) return details; - foreach (var module in modules) + foreach (KeyValuePair module in modules) { - var moduleCoverage = CalculateLineCoverage(module.Value); + CoverageDetails moduleCoverage = CalculateLineCoverage(module.Value); details.Covered += moduleCoverage.Covered; details.Total += moduleCoverage.Total; accumPercent += moduleCoverage.Percent; @@ -86,7 +89,7 @@ public int CalculateNpathComplexity(IList branches) } var paths = new Dictionary(); - foreach (var branch in branches) + foreach (BranchInfo branch in branches) { if (!paths.TryGetValue(branch.Offset, out int count)) { @@ -96,7 +99,7 @@ public int CalculateNpathComplexity(IList branches) } int npath = 1; - foreach (var branchPoints in paths.Values) + foreach (int branchPoints in paths.Values) { try { @@ -154,9 +157,9 @@ public int CalculateCyclomaticComplexity(Documents documents) public CoverageDetails CalculateBranchCoverage(Methods methods) { var details = new CoverageDetails(); - foreach (var method in methods) + foreach (KeyValuePair method in methods) { - var methodCoverage = CalculateBranchCoverage(method.Value.Branches); + CoverageDetails methodCoverage = CalculateBranchCoverage(method.Value.Branches); details.Covered += methodCoverage.Covered; details.Total += methodCoverage.Total; } @@ -166,9 +169,9 @@ public CoverageDetails CalculateBranchCoverage(Methods methods) public CoverageDetails CalculateBranchCoverage(Classes classes) { var details = new CoverageDetails(); - foreach (var @class in classes) + foreach (KeyValuePair @class in classes) { - var classCoverage = CalculateBranchCoverage(@class.Value); + CoverageDetails classCoverage = CalculateBranchCoverage(@class.Value); details.Covered += classCoverage.Covered; details.Total += classCoverage.Total; } @@ -178,9 +181,9 @@ public CoverageDetails CalculateBranchCoverage(Classes classes) public CoverageDetails CalculateBranchCoverage(Documents documents) { var details = new CoverageDetails(); - foreach (var document in documents) + foreach (KeyValuePair document in documents) { - var documentCoverage = CalculateBranchCoverage(document.Value); + CoverageDetails documentCoverage = CalculateBranchCoverage(document.Value); details.Covered += documentCoverage.Covered; details.Total += documentCoverage.Total; } @@ -189,15 +192,15 @@ public CoverageDetails CalculateBranchCoverage(Documents documents) public CoverageDetails CalculateBranchCoverage(Modules modules) { - var details = new CoverageDetails{ Modules = modules }; - var accumPercent = 0.0D; + var details = new CoverageDetails { Modules = modules }; + double accumPercent = 0.0D; if (modules.Count == 0) return details; - foreach (var module in modules) + foreach (KeyValuePair module in modules) { - var moduleCoverage = CalculateBranchCoverage(module.Value); + CoverageDetails moduleCoverage = CalculateBranchCoverage(module.Value); details.Covered += moduleCoverage.Covered; details.Total += moduleCoverage.Total; accumPercent += moduleCoverage.Percent; @@ -217,10 +220,10 @@ public CoverageDetails CalculateMethodCoverage(Lines lines) public CoverageDetails CalculateMethodCoverage(Methods methods) { var details = new CoverageDetails(); - var methodsWithLines = methods.Where(m => m.Value.Lines.Count > 0); - foreach (var method in methodsWithLines) + IEnumerable> methodsWithLines = methods.Where(m => m.Value.Lines.Count > 0); + foreach (KeyValuePair method in methodsWithLines) { - var methodCoverage = CalculateMethodCoverage(method.Value.Lines); + CoverageDetails methodCoverage = CalculateMethodCoverage(method.Value.Lines); details.Covered += methodCoverage.Covered; } details.Total = methodsWithLines.Count(); @@ -230,9 +233,9 @@ public CoverageDetails CalculateMethodCoverage(Methods methods) public CoverageDetails CalculateMethodCoverage(Classes classes) { var details = new CoverageDetails(); - foreach (var @class in classes) + foreach (KeyValuePair @class in classes) { - var classCoverage = CalculateMethodCoverage(@class.Value); + CoverageDetails classCoverage = CalculateMethodCoverage(@class.Value); details.Covered += classCoverage.Covered; details.Total += classCoverage.Total; } @@ -242,9 +245,9 @@ public CoverageDetails CalculateMethodCoverage(Classes classes) public CoverageDetails CalculateMethodCoverage(Documents documents) { var details = new CoverageDetails(); - foreach (var document in documents) + foreach (KeyValuePair document in documents) { - var documentCoverage = CalculateMethodCoverage(document.Value); + CoverageDetails documentCoverage = CalculateMethodCoverage(document.Value); details.Covered += documentCoverage.Covered; details.Total += documentCoverage.Total; } @@ -253,15 +256,15 @@ public CoverageDetails CalculateMethodCoverage(Documents documents) public CoverageDetails CalculateMethodCoverage(Modules modules) { - var details = new CoverageDetails{ Modules = modules }; - var accumPercent = 0.0D; + var details = new CoverageDetails { Modules = modules }; + double accumPercent = 0.0D; if (modules.Count == 0) return details; - foreach (var module in modules) + foreach (KeyValuePair module in modules) { - var moduleCoverage = CalculateMethodCoverage(module.Value); + CoverageDetails moduleCoverage = CalculateMethodCoverage(module.Value); details.Covered += moduleCoverage.Covered; details.Total += moduleCoverage.Total; accumPercent += moduleCoverage.Percent; @@ -270,4 +273,4 @@ public CoverageDetails CalculateMethodCoverage(Modules modules) return details; } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Enums/ThresholdStatistic.cs b/src/coverlet.core/Enums/ThresholdStatistic.cs index 9b7dd18ba..1dbb55dc0 100644 --- a/src/coverlet.core/Enums/ThresholdStatistic.cs +++ b/src/coverlet.core/Enums/ThresholdStatistic.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + namespace Coverlet.Core.Enums { internal enum ThresholdStatistic diff --git a/src/coverlet.core/Enums/ThresholdTypeFlags.cs b/src/coverlet.core/Enums/ThresholdTypeFlags.cs index 11a082178..9b24222a5 100644 --- a/src/coverlet.core/Enums/ThresholdTypeFlags.cs +++ b/src/coverlet.core/Enums/ThresholdTypeFlags.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; namespace Coverlet.Core.Enums diff --git a/src/coverlet.core/Exceptions.cs b/src/coverlet.core/Exceptions.cs index 81a6809aa..4eefd76ca 100644 --- a/src/coverlet.core/Exceptions.cs +++ b/src/coverlet.core/Exceptions.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Coverlet.Core.Exceptions { diff --git a/src/coverlet.core/Extensions/HelperExtensions.cs b/src/coverlet.core/Extensions/HelperExtensions.cs index fe8f45cae..30439c0c9 100644 --- a/src/coverlet.core/Extensions/HelperExtensions.cs +++ b/src/coverlet.core/Extensions/HelperExtensions.cs @@ -1,3 +1,5 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using Coverlet.Core.Attributes; @@ -7,10 +9,10 @@ namespace Coverlet.Core.Extensions internal static class HelperExtensions { [ExcludeFromCoverage] - public static TRet Maybe(this T value, Func action, TRet defValue = default(TRet)) + public static TRet Maybe(this T value, Func action, TRet defValue = default) where T : class { return (value != null) ? action(value) : defValue; } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Helpers/Console.cs b/src/coverlet.core/Helpers/Console.cs index eacddd323..8781b49de 100644 --- a/src/coverlet.core/Helpers/Console.cs +++ b/src/coverlet.core/Helpers/Console.cs @@ -1,5 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using Coverlet.Core.Abstractions; namespace Coverlet.Core.Helpers diff --git a/src/coverlet.core/Helpers/FileSystem.cs b/src/coverlet.core/Helpers/FileSystem.cs index 7213d3b4e..10dfc8f0a 100644 --- a/src/coverlet.core/Helpers/FileSystem.cs +++ b/src/coverlet.core/Helpers/FileSystem.cs @@ -1,5 +1,8 @@ -using Coverlet.Core.Abstractions; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; +using Coverlet.Core.Abstractions; namespace Coverlet.Core.Helpers { diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index 8a6827621..d546ecc27 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -8,7 +11,6 @@ using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Text.RegularExpressions; - using Coverlet.Core.Abstractions; namespace Coverlet.Core.Helpers @@ -81,14 +83,14 @@ public string[] GetCoverableModules(string moduleOrAppDirectory, string[] direct public bool HasPdb(string module, out bool embedded) { embedded = false; - using (var moduleStream = _fileSystem.OpenRead(module)) + using (Stream moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { - foreach (var entry in peReader.ReadDebugDirectory()) + foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { - var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); + CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); if (_sourceRootTranslator.ResolveFilePath(codeViewData.Path) == $"{Path.GetFileNameWithoutExtension(module)}.pdb") { // PDB is embedded @@ -117,12 +119,12 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot using (MetadataReaderProvider embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entry)) { MetadataReader metadataReader = embeddedMetadataProvider.GetMetadataReader(); - - var matchingResult = MatchDocumentsWithSources(metadataReader); - if (!matchingResult.allDocumentsMatch) + (bool allDocumentsMatch, string notFoundDocument) = MatchDocumentsWithSources(metadataReader); + + if (!allDocumentsMatch) { - firstNotFoundDocument = matchingResult.notFoundDocument; + firstNotFoundDocument = notFoundDocument; return false; } } @@ -138,16 +140,16 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; - using (var moduleStream = _fileSystem.OpenRead(module)) + using (Stream moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { - foreach (var entry in peReader.ReadDebugDirectory()) + foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { - var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); + CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); using Stream pdbStream = _fileSystem.OpenRead(_sourceRootTranslator.ResolveFilePath(codeViewData.Path)); - using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); + using var metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader metadataReader = null; try { @@ -159,11 +161,11 @@ public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDoc return true; } - var matchingResult = MatchDocumentsWithSources(metadataReader); + (bool allDocumentsMatch, string notFoundDocument) = MatchDocumentsWithSources(metadataReader); - if (!matchingResult.allDocumentsMatch) + if (!allDocumentsMatch) { - firstNotFoundDocument = matchingResult.notFoundDocument; + firstNotFoundDocument = notFoundDocument; return false; } } @@ -196,15 +198,15 @@ public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDoc public void BackupOriginalModule(string module, string identifier) { - var backupPath = GetBackupPath(module, identifier); - var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb"); + string backupPath = GetBackupPath(module, identifier); + string backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb"); _fileSystem.Copy(module, backupPath, true); if (!_backupList.TryAdd(module, backupPath)) { throw new ArgumentException($"Key already added '{module}'"); } - var symbolFile = Path.ChangeExtension(module, ".pdb"); + string symbolFile = Path.ChangeExtension(module, ".pdb"); if (_fileSystem.Exists(symbolFile)) { _fileSystem.Copy(symbolFile, backupSymbolPath, true); @@ -217,12 +219,12 @@ public void BackupOriginalModule(string module, string identifier) public virtual void RestoreOriginalModule(string module, string identifier) { - var backupPath = GetBackupPath(module, identifier); - var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb"); + string backupPath = GetBackupPath(module, identifier); + string backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb"); // Restore the original module - retry up to 10 times, since the destination file could be locked // See: https://github.com/tonerdo/coverlet/issues/25 - var retryStrategy = CreateRetryStrategy(); + Func retryStrategy = CreateRetryStrategy(); _retryHelper.Retry(() => { @@ -247,7 +249,7 @@ public virtual void RestoreOriginalModules() { // Restore the original module - retry up to 10 times, since the destination file could be locked // See: https://github.com/tonerdo/coverlet/issues/25 - var retryStrategy = CreateRetryStrategy(); + Func retryStrategy = CreateRetryStrategy(); foreach (string key in _backupList.Keys.ToList()) { @@ -263,7 +265,7 @@ public virtual void RestoreOriginalModules() public void DeleteHitsFile(string path) { - var retryStrategy = CreateRetryStrategy(); + Func retryStrategy = CreateRetryStrategy(); _retryHelper.Retry(() => _fileSystem.Delete(path), retryStrategy, RetryAttempts); } @@ -308,7 +310,7 @@ public bool IsModuleExcluded(string module, string[] excludeFilters) if (module == null) return false; - foreach (var filter in excludeFilters) + foreach (string filter in excludeFilters) { string typePattern = filter.Substring(filter.IndexOf(']') + 1); @@ -336,7 +338,7 @@ public bool IsModuleIncluded(string module, string[] includeFilters) if (module == null) return false; - foreach (var filter in includeFilters) + foreach (string filter in includeFilters) { string modulePattern = filter.Substring(1, filter.IndexOf(']') - 1); @@ -391,7 +393,7 @@ private bool IsTypeFilterMatch(string module, string type, string[] filters) Debug.Assert(module != null); Debug.Assert(filters != null); - foreach (var filter in filters) + foreach (string filter in filters) { string typePattern = filter.Substring(filter.IndexOf(']') + 1); string modulePattern = filter.Substring(1, filter.IndexOf(']') - 1); @@ -454,8 +456,8 @@ private bool IsAssembly(string filePath) private bool IsUnknownModuleInFSharpAssembly(Guid languageGuid, string docName) { // https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md#document-table-0x30 - return languageGuid.Equals(new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3")) + return languageGuid.Equals(new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3")) && docName.EndsWith("unknown"); } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Helpers/ProcessExitHandler.cs b/src/coverlet.core/Helpers/ProcessExitHandler.cs index 7083e27ae..1e570f07f 100644 --- a/src/coverlet.core/Helpers/ProcessExitHandler.cs +++ b/src/coverlet.core/Helpers/ProcessExitHandler.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using Coverlet.Core.Abstractions; namespace Coverlet.Core.Helpers diff --git a/src/coverlet.core/Helpers/RetryHelper.cs b/src/coverlet.core/Helpers/RetryHelper.cs index 652cb1cfb..dcf3fa9d0 100644 --- a/src/coverlet.core/Helpers/RetryHelper.cs +++ b/src/coverlet.core/Helpers/RetryHelper.cs @@ -1,7 +1,10 @@ -using Coverlet.Core.Abstractions; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Threading; +using Coverlet.Core.Abstractions; namespace Coverlet.Core.Helpers { @@ -59,4 +62,4 @@ public T Do( throw new AggregateException(exceptions); } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Helpers/SourceRootTranslator.cs b/src/coverlet.core/Helpers/SourceRootTranslator.cs index b75901ada..f03c83ff5 100644 --- a/src/coverlet.core/Helpers/SourceRootTranslator.cs +++ b/src/coverlet.core/Helpers/SourceRootTranslator.cs @@ -1,8 +1,11 @@ -using Coverlet.Core.Abstractions; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using Coverlet.Core.Abstractions; namespace Coverlet.Core.Helpers { @@ -52,7 +55,7 @@ private Dictionary> LoadSourceToDeterministicPathMapping(Di throw new ArgumentNullException(nameof(sourceRootMapping)); } - Dictionary> sourceToDeterministicPathMapping = new Dictionary>(); + var sourceToDeterministicPathMapping = new Dictionary>(); foreach (KeyValuePair> sourceRootMappingEntry in sourceRootMapping) { foreach (SourceRootMapping originalPath in sourceRootMappingEntry.Value) @@ -70,7 +73,7 @@ private Dictionary> LoadSourceToDeterministicPathMapping(Di private Dictionary> LoadSourceRootMapping(string directory) { - Dictionary> mapping = new Dictionary>(); + var mapping = new Dictionary>(); string mappingFilePath = Path.Combine(directory, MappingFileName); if (!_fileSystem.Exists(mappingFilePath)) @@ -138,7 +141,7 @@ public string ResolveFilePath(string originalFileName) public string ResolveDeterministicPath(string originalFileName) { - foreach (var originalPath in _sourceToDeterministicPathMapping) + foreach (KeyValuePair> originalPath in _sourceToDeterministicPathMapping) { if (originalFileName.StartsWith(originalPath.Key)) { diff --git a/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs b/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs index 2624475f3..0f89edf5f 100644 --- a/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs +++ b/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs @@ -1,8 +1,10 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; - using Coverlet.Core.Abstractions; using Coverlet.Core.Exceptions; using Microsoft.Extensions.DependencyModel; @@ -167,8 +169,8 @@ internal AssemblyDefinition TryWithCustomResolverOnDotNetCore(AssemblyNameRefere throw new AssemblyResolutionException(name); } - using DependencyContextJsonReader contextJsonReader = new DependencyContextJsonReader(); - Dictionary> libraries = new Dictionary>(); + using var contextJsonReader = new DependencyContextJsonReader(); + var libraries = new Dictionary>(); foreach (string fileName in Directory.GetFiles(Path.GetDirectoryName(_modulePath), "*.deps.json")) { @@ -248,7 +250,7 @@ public bool TryResolveAssemblyPaths(CompilationLibrary library, List ass continue; } - foreach (var file in Directory.GetFiles(sharedFrameworkPath)) + foreach (string file in Directory.GetFiles(sharedFrameworkPath)) { if (Path.GetFileName(file).Equals(dllName, StringComparison.OrdinalIgnoreCase)) { diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index cf80e90a3..9b2ca6fc7 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Diagnostics; @@ -5,11 +8,10 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; - -using Coverlet.Core.Instrumentation.Reachability; using Coverlet.Core.Abstractions; using Coverlet.Core.Attributes; using Coverlet.Core.Helpers; +using Coverlet.Core.Instrumentation.Reachability; using Coverlet.Core.Symbols; using Microsoft.Extensions.FileSystemGlobbing; using Mono.Cecil; @@ -183,7 +185,7 @@ private bool Is_System_Threading_Interlocked_CoreLib_Type(TypeDefinition type) // locking issues if we do it while writing. private void CreateReachabilityHelper() { - using (var stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.Read)) + using (Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.Read)) using (var resolver = new NetstandardAwareAssemblyResolver(_module, _logger)) { resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); @@ -204,7 +206,7 @@ private void InstrumentModule() { CreateReachabilityHelper(); - using (var stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite)) + using (Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite)) using (var resolver = new NetstandardAwareAssemblyResolver(_module, _logger)) { resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); @@ -226,11 +228,11 @@ private void InstrumentModule() } } - var containsAppContext = module.GetType(nameof(System), nameof(AppContext)) != null; - var types = module.GetTypes(); + bool containsAppContext = module.GetType(nameof(System), nameof(AppContext)) != null; + IEnumerable types = module.GetTypes(); AddCustomModuleTrackerToModule(module); - var sourceLinkDebugInfo = module.CustomDebugInformations.FirstOrDefault(c => c.Kind == CustomDebugInformationKind.SourceLink); + CustomDebugInformation sourceLinkDebugInfo = module.CustomDebugInformations.FirstOrDefault(c => c.Kind == CustomDebugInformationKind.SourceLink); if (sourceLinkDebugInfo != null) { _result.SourceLink = ((SourceLinkDebugInformation)sourceLinkDebugInfo).Content; @@ -294,11 +296,11 @@ private void InstrumentModule() customTrackerUnloadModule.Parameters.Add(new ParameterDefinition(eventArgsType)); var appContextType = new TypeReference(nameof(System), nameof(AppContext), module, module.TypeSystem.CoreLibrary); - var onProcessExitMethod = new MethodReference("OnProcessExit", module.TypeSystem.Void, appContextType).Resolve(); - var onProcessExitIl = onProcessExitMethod.Body.GetILProcessor(); + MethodDefinition onProcessExitMethod = new MethodReference("OnProcessExit", module.TypeSystem.Void, appContextType).Resolve(); + ILProcessor onProcessExitIl = onProcessExitMethod.Body.GetILProcessor(); // Put the OnProcessExit body inside try/finally to ensure the call to the UnloadModule. - var lastInst = onProcessExitMethod.Body.Instructions.Last(); + Instruction lastInst = onProcessExitMethod.Body.Instructions.Last(); var firstNullParam = Instruction.Create(OpCodes.Ldnull); var secondNullParam = Instruction.Create(OpCodes.Ldnull); var callUnload = Instruction.Create(OpCodes.Call, customTrackerUnloadModule); @@ -307,16 +309,16 @@ private void InstrumentModule() onProcessExitIl.InsertAfter(secondNullParam, callUnload); var endFinally = Instruction.Create(OpCodes.Endfinally); onProcessExitIl.InsertAfter(callUnload, endFinally); - var ret = onProcessExitIl.Create(OpCodes.Ret); - var leaveAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); + Instruction ret = onProcessExitIl.Create(OpCodes.Ret); + Instruction leaveAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); onProcessExitIl.InsertAfter(endFinally, ret); - foreach (var inst in onProcessExitMethod.Body.Instructions.ToArray()) + foreach (Instruction inst in onProcessExitMethod.Body.Instructions.ToArray()) { // Patch ret to leave after the finally if (inst.OpCode == OpCodes.Ret && inst != ret) { - var leaveBodyInstAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); - var prevInst = inst.Previous; + Instruction leaveBodyInstAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); + Instruction prevInst = inst.Previous; onProcessExitMethod.Body.Instructions.Remove(inst); onProcessExitIl.InsertAfter(prevInst, leaveBodyInstAfterFinally); } @@ -339,7 +341,7 @@ private void InstrumentModule() private void AddCustomModuleTrackerToModule(ModuleDefinition module) { - using (AssemblyDefinition coverletInstrumentationAssembly = AssemblyDefinition.ReadAssembly(typeof(ModuleTrackerTemplate).Assembly.Location)) + using (var coverletInstrumentationAssembly = AssemblyDefinition.ReadAssembly(typeof(ModuleTrackerTemplate).Assembly.Location)) { TypeDefinition moduleTrackerTemplate = coverletInstrumentationAssembly.MainModule.GetType( "Coverlet.Core.Instrumentation", nameof(ModuleTrackerTemplate)); @@ -367,14 +369,14 @@ private void AddCustomModuleTrackerToModule(ModuleDefinition module) foreach (MethodDefinition methodDef in moduleTrackerTemplate.Methods) { - MethodDefinition methodOnCustomType = new MethodDefinition(methodDef.Name, methodDef.Attributes, methodDef.ReturnType); + var methodOnCustomType = new MethodDefinition(methodDef.Name, methodDef.Attributes, methodDef.ReturnType); - foreach (var parameter in methodDef.Parameters) + foreach (ParameterDefinition parameter in methodDef.Parameters) { methodOnCustomType.Parameters.Add(new ParameterDefinition(module.ImportReference(parameter.ParameterType))); } - foreach (var variable in methodDef.Body.Variables) + foreach (VariableDefinition variable in methodDef.Body.Variables) { methodOnCustomType.Body.Variables.Add(new VariableDefinition(module.ImportReference(variable.VariableType))); } @@ -398,7 +400,7 @@ private void AddCustomModuleTrackerToModule(ModuleDefinition module) { // Move to the custom type var updatedMethodReference = new MethodReference(methodReference.Name, methodReference.ReturnType, _customTrackerTypeDef); - foreach (var parameter in methodReference.Parameters) + foreach (ParameterDefinition parameter in methodReference.Parameters) updatedMethodReference.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, module.ImportReference(parameter.ParameterType))); instr.Operand = updatedMethodReference; @@ -416,7 +418,7 @@ private void AddCustomModuleTrackerToModule(ModuleDefinition module) ilProcessor.Append(instr); } - foreach (var handler in methodDef.Body.ExceptionHandlers) + foreach (ExceptionHandler handler in methodDef.Body.ExceptionHandlers) { if (handler.CatchType != null) { @@ -469,12 +471,12 @@ private bool IsMethodOfCompilerGeneratedClassOfAsyncStateMachineToBeExcluded(Met private void InstrumentType(TypeDefinition type) { - var methods = type.GetMethods(); + IEnumerable methods = type.GetMethods(); // We keep ordinal index because it's the way used by compiler for generated types/methods to // avoid ambiguity int ordinal = -1; - foreach (var method in methods) + foreach (MethodDefinition method in methods) { MethodDefinition actualMethod = method; IEnumerable customAttributes = method.CustomAttributes; @@ -516,8 +518,8 @@ private void InstrumentType(TypeDefinition type) } } - var ctors = type.GetConstructors(); - foreach (var ctor in ctors) + IEnumerable ctors = type.GetConstructors(); + foreach (MethodDefinition ctor in ctors) { if (!ctor.CustomAttributes.Any(IsExcludeAttribute)) { @@ -528,7 +530,7 @@ private void InstrumentType(TypeDefinition type) private void InstrumentMethod(MethodDefinition method) { - var sourceFile = method.DebugInformation.SequencePoints.Select(s => _sourceRootTranslator.ResolveFilePath(s.Document.Url)).FirstOrDefault(); + string sourceFile = method.DebugInformation.SequencePoints.Select(s => _sourceRootTranslator.ResolveFilePath(s.Document.Url)).FirstOrDefault(); if (!string.IsNullOrEmpty(sourceFile) && _excludedFilesHelper.Exclude(sourceFile)) { if (!(_excludedSourceFiles ??= new List()).Contains(sourceFile)) @@ -538,7 +540,7 @@ private void InstrumentMethod(MethodDefinition method) return; } - var methodBody = GetMethodBody(method); + MethodBody methodBody = GetMethodBody(method); if (methodBody == null) return; @@ -563,29 +565,29 @@ private void InstrumentIL(MethodDefinition method) { method.Body.SimplifyMacros(); ILProcessor processor = method.Body.GetILProcessor(); - var index = 0; - var count = processor.Body.Instructions.Count; - var branchPoints = _cecilSymbolHelper.GetBranchPoints(method); - var unreachableRanges = _reachabilityHelper.FindUnreachableIL(processor.Body.Instructions, processor.Body.ExceptionHandlers); - var currentUnreachableRangeIx = 0; + int index = 0; + int count = processor.Body.Instructions.Count; + IReadOnlyList branchPoints = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Immutable.ImmutableArray unreachableRanges = _reachabilityHelper.FindUnreachableIL(processor.Body.Instructions, processor.Body.ExceptionHandlers); + int currentUnreachableRangeIx = 0; for (int n = 0; n < count; n++) { - var currentInstruction = processor.Body.Instructions[index]; - var sequencePoint = method.DebugInformation.GetSequencePoint(currentInstruction); - var targetedBranchPoints = branchPoints.Where(p => p.EndOffset == currentInstruction.Offset); + Instruction currentInstruction = processor.Body.Instructions[index]; + SequencePoint sequencePoint = method.DebugInformation.GetSequencePoint(currentInstruction); + IEnumerable targetedBranchPoints = branchPoints.Where(p => p.EndOffset == currentInstruction.Offset); // make sure we're looking at the correct unreachable range (if any) - var instrOffset = currentInstruction.Offset; + int instrOffset = currentInstruction.Offset; while (currentUnreachableRangeIx < unreachableRanges.Length && instrOffset > unreachableRanges[currentUnreachableRangeIx].EndOffset) { currentUnreachableRangeIx++; } // determine if the unreachable - var isUnreachable = false; + bool isUnreachable = false; if (currentUnreachableRangeIx < unreachableRanges.Length) { - var range = unreachableRanges[currentUnreachableRangeIx]; + ReachabilityHelper.UnreachableRange range = unreachableRanges[currentUnreachableRangeIx]; isUnreachable = instrOffset >= range.StartOffset && instrOffset <= range.EndOffset; } @@ -604,8 +606,8 @@ private void InstrumentIL(MethodDefinition method) continue; } - var firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, sequencePoint); - foreach (var bodyInstruction in processor.Body.Instructions) + Instruction firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, sequencePoint); + foreach (Instruction bodyInstruction in processor.Body.Instructions) ReplaceInstructionTarget(bodyInstruction, currentInstruction, firstInjectedInstrumentedOpCode); foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers) @@ -614,7 +616,7 @@ private void InstrumentIL(MethodDefinition method) index += 2; } - foreach (var branchTarget in targetedBranchPoints) + foreach (BranchPoint branchTarget in targetedBranchPoints) { /* * Skip branches with no sequence point reference for now. @@ -625,8 +627,8 @@ private void InstrumentIL(MethodDefinition method) if (branchTarget.StartLine == -1 || branchTarget.Document == null) continue; - var firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, branchTarget); - foreach (var bodyInstruction in processor.Body.Instructions) + Instruction firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, branchTarget); + foreach (Instruction bodyInstruction in processor.Body.Instructions) ReplaceInstructionTarget(bodyInstruction, currentInstruction, firstInjectedInstrumentedOpCode); foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers) @@ -643,7 +645,7 @@ private void InstrumentIL(MethodDefinition method) private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, SequencePoint sequencePoint) { - if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url), out var document)) + if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url), out Document document)) { document = new Document { Path = _sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url) }; document.Index = _result.Documents.Count; @@ -663,14 +665,14 @@ private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint) { - if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(branchPoint.Document), out var document)) + if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(branchPoint.Document), out Document document)) { document = new Document { Path = _sourceRootTranslator.ResolveFilePath(branchPoint.Document) }; document.Index = _result.Documents.Count; _result.Documents.Add(document.Path, document); } - BranchKey key = new BranchKey(branchPoint.StartLine, (int)branchPoint.Ordinal); + var key = new BranchKey(branchPoint.StartLine, (int)branchPoint.Ordinal); if (!document.Branches.ContainsKey(key)) { document.Branches.Add( @@ -815,7 +817,7 @@ private bool IsSynthesizedMemberToBeExcluded(IMemberDefinition definition) } // Check methods members and compiler generated types - foreach (var excludedMethods in _excludedMethods) + foreach ((MethodDefinition, int) excludedMethods in _excludedMethods) { // Exclude this member if declaring type is the same of the excluded method and // the name is synthesized from the name of the excluded method. @@ -868,34 +870,34 @@ private class CoreLibMetadataImporter : IMetadataImporter public CoreLibMetadataImporter(ModuleDefinition module) { this.module = module; - this.defaultMetadataImporter = new DefaultMetadataImporter(module); + defaultMetadataImporter = new DefaultMetadataImporter(module); } public AssemblyNameReference ImportReference(AssemblyNameReference reference) { - return this.defaultMetadataImporter.ImportReference(reference); + return defaultMetadataImporter.ImportReference(reference); } public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context) { - var importedRef = this.defaultMetadataImporter.ImportReference(type, context); + TypeReference importedRef = defaultMetadataImporter.ImportReference(type, context); importedRef.GetElementType().Scope = module.TypeSystem.CoreLibrary; return importedRef; } public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context) { - var importedRef = this.defaultMetadataImporter.ImportReference(field, context); + FieldReference importedRef = defaultMetadataImporter.ImportReference(field, context); importedRef.FieldType.GetElementType().Scope = module.TypeSystem.CoreLibrary; return importedRef; } public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context) { - var importedRef = this.defaultMetadataImporter.ImportReference(method, context); + MethodReference importedRef = defaultMetadataImporter.ImportReference(method, context); importedRef.DeclaringType.GetElementType().Scope = module.TypeSystem.CoreLibrary; - foreach (var parameter in importedRef.Parameters) + foreach (ParameterDefinition parameter in importedRef.Parameters) { if (parameter.ParameterType.Scope == module.TypeSystem.CoreLibrary) { @@ -919,14 +921,14 @@ public MethodReference ImportReference(MethodReference method, IGenericParameter // Exclude files helper https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.filesystemglobbing.matcher?view=aspnetcore-2.2 internal class ExcludedFilesHelper { - Matcher _matcher; + readonly Matcher _matcher; public ExcludedFilesHelper(string[] excludes, ILogger logger) { if (excludes != null && excludes.Length > 0) { _matcher = new Matcher(); - foreach (var excludeRule in excludes) + foreach (string excludeRule in excludes) { if (excludeRule is null) { diff --git a/src/coverlet.core/Instrumentation/InstrumenterResult.cs b/src/coverlet.core/Instrumentation/InstrumenterResult.cs index a575f7739..69a6ab24a 100644 --- a/src/coverlet.core/Instrumentation/InstrumenterResult.cs +++ b/src/coverlet.core/Instrumentation/InstrumenterResult.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Diagnostics; @@ -47,11 +50,11 @@ internal class BranchKey : IEquatable public override bool Equals(object obj) => Equals(obj); - public bool Equals(BranchKey other) => other is BranchKey branchKey && branchKey.Line == this.Line && branchKey.Ordinal == this.Ordinal; + public bool Equals(BranchKey other) => other is BranchKey branchKey && branchKey.Line == Line && branchKey.Ordinal == Ordinal; public override int GetHashCode() { - return (this.Line, this.Ordinal).GetHashCode(); + return (Line, Ordinal).GetHashCode(); } } diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index 8321a704f..b538143be 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -1,5 +1,7 @@ -using System; -using System.Diagnostics; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; @@ -25,7 +27,7 @@ internal static class ModuleTrackerTemplate public static bool SingleHit; public static bool FlushHitFile; private static readonly bool _enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) ? result == 1 : false; - private static string _sessionId = Guid.NewGuid().ToString(); + private static readonly string _sessionId = Guid.NewGuid().ToString(); static ModuleTrackerTemplate() { @@ -171,8 +173,8 @@ private static void WriteHits(object sender) { if (_enableLog) { - Assembly currentAssembly = Assembly.GetExecutingAssembly(); - DirectoryInfo location = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(currentAssembly.Location), "TrackersHitsLog")); + var currentAssembly = Assembly.GetExecutingAssembly(); + var location = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(currentAssembly.Location), "TrackersHitsLog")); location.Create(); string logFile = Path.Combine(location.FullName, $"{Path.GetFileName(currentAssembly.Location)}_{DateTime.UtcNow.Ticks}_{_sessionId}.txt"); using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) diff --git a/src/coverlet.core/Instrumentation/ReachabilityHelper.cs b/src/coverlet.core/Instrumentation/ReachabilityHelper.cs index 4d7474ea6..dee555a21 100644 --- a/src/coverlet.core/Instrumentation/ReachabilityHelper.cs +++ b/src/coverlet.core/Instrumentation/ReachabilityHelper.cs @@ -1,10 +1,13 @@ -using Coverlet.Core.Abstractions; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Immutable; using System.Linq; +using Coverlet.Core.Abstractions; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Collections.Generic; namespace Coverlet.Core.Instrumentation.Reachability { @@ -252,11 +255,11 @@ public static ReachabilityHelper CreateForModule(ModuleDefinition module, string return new ReachabilityHelper(ImmutableHashSet.Empty); } - var processedMethods = ImmutableHashSet.Empty; - var doNotReturn = ImmutableHashSet.CreateBuilder(); - foreach (var type in module.Types) + ImmutableHashSet processedMethods = ImmutableHashSet.Empty; + ImmutableHashSet.Builder doNotReturn = ImmutableHashSet.CreateBuilder(); + foreach (TypeDefinition type in module.Types) { - foreach (var mtd in type.Methods) + foreach (MethodDefinition mtd in type.Methods) { if (mtd.IsNative) { @@ -278,14 +281,14 @@ public static ReachabilityHelper CreateForModule(ModuleDefinition module, string continue; } - foreach (var instr in body.Instructions) + foreach (Instruction instr in body.Instructions) { - if (!IsCall(instr, out var calledMtd)) + if (!IsCall(instr, out MethodReference calledMtd)) { continue; } - var token = calledMtd.MetadataToken; + MetadataToken token = calledMtd.MetadataToken; if (processedMethods.Contains(token)) { continue; @@ -314,8 +317,8 @@ public static ReachabilityHelper CreateForModule(ModuleDefinition module, string continue; } - var hasDoesNotReturnAttribute = false; - foreach (var attr in mtdDef.CustomAttributes) + bool hasDoesNotReturnAttribute = false; + foreach (CustomAttribute attr in mtdDef.CustomAttributes) { if (Array.IndexOf(doesNotReturnAttributes, attr.AttributeType.Name) != -1) { @@ -333,7 +336,7 @@ public static ReachabilityHelper CreateForModule(ModuleDefinition module, string } } - var doNoReturnTokens = doNotReturn.ToImmutable(); + ImmutableHashSet doNoReturnTokens = doNotReturn.ToImmutable(); return new ReachabilityHelper(doNoReturnTokens); } @@ -374,7 +377,7 @@ public ImmutableArray FindUnreachableIL(Collection.Empty; } - var (mayContainUnreachableCode, branches) = AnalyzeInstructions(instrs, exceptionHandlers); + (bool mayContainUnreachableCode, ImmutableArray branches) = AnalyzeInstructions(instrs, exceptionHandlers); // no need to do any more work, nothing unreachable here if (!mayContainUnreachableCode) @@ -382,9 +385,9 @@ public ImmutableArray FindUnreachableIL(Collection.Empty; } - var lastInstr = instrs[instrs.Count - 1]; + Instruction lastInstr = instrs[instrs.Count - 1]; - var blocks = CreateBasicBlocks(instrs, exceptionHandlers, branches); + ImmutableArray blocks = CreateBasicBlocks(instrs, exceptionHandlers, branches); DetermineHeadReachability(blocks); return DetermineUnreachableRanges(blocks, lastInstr.Offset); @@ -396,16 +399,16 @@ public ImmutableArray FindUnreachableIL(Collection private (bool MayContainUnreachableCode, ImmutableArray Branches) AnalyzeInstructions(Collection instrs, Collection exceptionHandlers) { - var containsDoesNotReturnCall = false; + bool containsDoesNotReturnCall = false; - var ret = ImmutableArray.CreateBuilder(); - foreach (var i in instrs) + ImmutableArray.Builder ret = ImmutableArray.CreateBuilder(); + foreach (Instruction i in instrs) { containsDoesNotReturnCall = containsDoesNotReturnCall || DoesNotReturn(i); if (BRANCH_OPCODES.Contains(i.OpCode)) { - var (singleTargetOffset, multiTargetOffsets) = GetInstructionTargets(i, exceptionHandlers); + (int? singleTargetOffset, ImmutableArray multiTargetOffsets) = GetInstructionTargets(i, exceptionHandlers); if (singleTargetOffset != null) { @@ -435,7 +438,7 @@ private static (int? SingleTargetOffset, ImmutableArray MultiTargetOffsets) singleTargetOffset = null; multiTargetOffsets = ImmutableArray.Create(i.Next.Offset); - foreach (var instr in multiTarget) + foreach (Instruction instr in multiTarget) { // in practice these are small arrays, so a scan should be fine if (multiTargetOffsets.Contains(instr.Offset)) @@ -467,15 +470,15 @@ private static (int? SingleTargetOffset, ImmutableArray MultiTargetOffsets) // flow is allowed so we can scan backwards to see find the block ExceptionHandler filterForHandler = null; - foreach (var handler in exceptionHandlers) + foreach (ExceptionHandler handler in exceptionHandlers) { if (handler.FilterStart == null) { continue; } - var startsAt = handler.FilterStart; - var cur = startsAt; + Instruction startsAt = handler.FilterStart; + Instruction cur = startsAt; while (cur != null && cur.Offset < i.Offset) { cur = cur.Next; @@ -526,13 +529,13 @@ private static (int? SingleTargetOffset, ImmutableArray MultiTargetOffsets) /// private ImmutableArray DetermineUnreachableRanges(ImmutableArray blocks, int lastInstructionOffset) { - var ret = ImmutableArray.CreateBuilder(); + ImmutableArray.Builder ret = ImmutableArray.CreateBuilder(); - var endOfMethodOffset = lastInstructionOffset + 1; // add 1 so we point _past_ the end of the method + int endOfMethodOffset = lastInstructionOffset + 1; // add 1 so we point _past_ the end of the method - for (var curBlockIx = 0; curBlockIx < blocks.Length; curBlockIx++) + for (int curBlockIx = 0; curBlockIx < blocks.Length; curBlockIx++) { - var curBlock = blocks[curBlockIx]; + BasicBlock curBlock = blocks[curBlockIx]; int endOfCurBlockOffset; if (curBlockIx == blocks.Length - 1) @@ -553,11 +556,11 @@ private ImmutableArray DetermineUnreachableRanges(ImmutableArr } // tail isn't reachable, which means there's a call to something that doesn't return... - var doesNotReturnInstr = curBlock.UnreachableAfter; + Instruction doesNotReturnInstr = curBlock.UnreachableAfter; // and it's everything _after_ the following instruction that is unreachable // so record the following instruction through the end of the block - var followingInstr = doesNotReturnInstr.Next; + Instruction followingInstr = doesNotReturnInstr.Next; ret.Add(new UnreachableRange(followingInstr.Offset, endOfCurBlockOffset)); } @@ -581,13 +584,13 @@ private void DetermineHeadReachability(ImmutableArray blocks) { var blockLookup = blocks.ToImmutableDictionary(b => b.StartOffset); - var headBlock = blockLookup[0]; + BasicBlock headBlock = blockLookup[0]; var knownLive = ImmutableStack.Create(headBlock); while (!knownLive.IsEmpty) { - knownLive = knownLive.Pop(out var block); + knownLive = knownLive.Pop(out BasicBlock block); if (block.HeadReachable) { @@ -601,18 +604,18 @@ private void DetermineHeadReachability(ImmutableArray blocks) if (block.TailReachable) { // we can reach all the blocks it might flow to - foreach (var reachableOffset in block.BranchesTo) + foreach (int reachableOffset in block.BranchesTo) { - var reachableBlock = blockLookup[reachableOffset]; + BasicBlock reachableBlock = blockLookup[reachableOffset]; knownLive = knownLive.Push(reachableBlock); } } // if the block is covered by an exception handler, then executing _any_ instruction in it // could conceivably cause those handlers to be visited - foreach (var exceptionHandlerOffset in block.ExceptionBranchesTo) + foreach (int exceptionHandlerOffset in block.ExceptionBranchesTo) { - var reachableHandler = blockLookup[exceptionHandlerOffset]; + BasicBlock reachableHandler = blockLookup[exceptionHandlerOffset]; knownLive = knownLive.Push(reachableHandler); } } @@ -629,16 +632,16 @@ private void DetermineHeadReachability(ImmutableArray blocks) private ImmutableArray CreateBasicBlocks(Collection instrs, Collection exceptionHandlers, ImmutableArray branches) { // every branch-like instruction starts or stops a block - var branchInstrLocs = branches.ToLookup(i => i.Offset); + ILookup branchInstrLocs = branches.ToLookup(i => i.Offset); var branchInstrOffsets = branchInstrLocs.Select(k => k.Key).ToImmutableHashSet(); // every target that might be branched to starts or stops a block - var branchTargetOffsetsBuilder = ImmutableHashSet.CreateBuilder(); - foreach (var branch in branches) + ImmutableHashSet.Builder branchTargetOffsetsBuilder = ImmutableHashSet.CreateBuilder(); + foreach (BranchInstruction branch in branches) { if (branch.HasMultiTargets) { - foreach (var target in branch.TargetOffsets) + foreach (int target in branch.TargetOffsets) { branchTargetOffsetsBuilder.Add(target); } @@ -651,7 +654,7 @@ private ImmutableArray CreateBasicBlocks(Collection ins // every exception handler an entry point // either it's handler, or it's filter (if present) - foreach (var handler in exceptionHandlers) + foreach (ExceptionHandler handler in exceptionHandlers) { if (handler.FilterStart != null) { @@ -663,18 +666,18 @@ private ImmutableArray CreateBasicBlocks(Collection ins } } - var branchTargetOffsets = branchTargetOffsetsBuilder.ToImmutable(); + ImmutableHashSet branchTargetOffsets = branchTargetOffsetsBuilder.ToImmutable(); // ending the method is also important - var endOfMethodOffset = instrs[instrs.Count - 1].Offset; + int endOfMethodOffset = instrs[instrs.Count - 1].Offset; - var blocks = ImmutableArray.Empty; + ImmutableArray blocks = ImmutableArray.Empty; int? blockStartedAt = null; Instruction unreachableAfter = null; - foreach (var i in instrs) + foreach (Instruction i in instrs) { - var offset = i.Offset; - var branchesAtLoc = branchInstrLocs[offset]; + int offset = i.Offset; + System.Collections.Generic.IEnumerable branchesAtLoc = branchInstrLocs[offset]; if (blockStartedAt == null) { @@ -682,19 +685,19 @@ private ImmutableArray CreateBasicBlocks(Collection ins unreachableAfter = null; } - var isBranch = branchInstrOffsets.Contains(offset); - var isFollowedByBranchTarget = i.Next != null && branchTargetOffsets.Contains(i.Next.Offset); - var isEndOfMtd = endOfMethodOffset == offset; + bool isBranch = branchInstrOffsets.Contains(offset); + bool isFollowedByBranchTarget = i.Next != null && branchTargetOffsets.Contains(i.Next.Offset); + bool isEndOfMtd = endOfMethodOffset == offset; if (unreachableAfter == null && DoesNotReturn(i)) { unreachableAfter = i; } - var blockEnds = isBranch || isFollowedByBranchTarget || isEndOfMtd; + bool blockEnds = isBranch || isFollowedByBranchTarget || isEndOfMtd; if (blockEnds) { - var nextInstr = i.Next; + Instruction nextInstr = i.Next; // figure out all the different places the basic block could lead to ImmutableArray goesTo; @@ -702,7 +705,7 @@ private ImmutableArray CreateBasicBlocks(Collection ins { // it ends in a branch, where all does it branch? goesTo = ImmutableArray.Empty; - foreach (var branch in branchesAtLoc) + foreach (BranchInstruction branch in branchesAtLoc) { if (branch.HasMultiTargets) { @@ -725,30 +728,30 @@ private ImmutableArray CreateBasicBlocks(Collection ins goesTo = ImmutableArray.Empty; } - var exceptionSwitchesTo = ImmutableArray.Empty; + ImmutableArray exceptionSwitchesTo = ImmutableArray.Empty; // if the block is covered by any exception handlers then // it is possible that it will branch to its handler block - foreach (var handler in exceptionHandlers) + foreach (ExceptionHandler handler in exceptionHandlers) { - var tryStart = handler.TryStart.Offset; - var tryEnd = handler.TryEnd.Offset; + int tryStart = handler.TryStart.Offset; + int tryEnd = handler.TryEnd.Offset; - var containsStartOfTry = + bool containsStartOfTry = tryStart >= blockStartedAt.Value && tryStart <= i.Offset; - var containsEndOfTry = + bool containsEndOfTry = tryEnd >= blockStartedAt.Value && tryEnd <= i.Offset; - var blockInsideTry = blockStartedAt.Value >= tryStart && i.Offset <= tryEnd; + bool blockInsideTry = blockStartedAt.Value >= tryStart && i.Offset <= tryEnd; // blocks do not necessarily align to the TRY part of exception handlers, so we need to handle three cases: // - the try _starts_ in the block // - the try _ends_ in the block // - the try complete covers the block, but starts and ends before and after it (respectively) - var tryOverlapsBlock = containsStartOfTry || containsEndOfTry || blockInsideTry; + bool tryOverlapsBlock = containsStartOfTry || containsEndOfTry || blockInsideTry; if (!tryOverlapsBlock) { @@ -783,7 +786,7 @@ private ImmutableArray CreateBasicBlocks(Collection ins /// private bool DoesNotReturn(Instruction instr) { - if (!IsCall(instr, out var mtd)) + if (!IsCall(instr, out MethodReference mtd)) { return false; } @@ -798,7 +801,7 @@ private bool DoesNotReturn(Instruction instr) /// private static bool IsCall(Instruction instr, out MethodReference mtd) { - var opcode = instr.OpCode; + OpCode opcode = instr.OpCode; if (opcode != OpCodes.Call && opcode != OpCodes.Callvirt) { mtd = null; diff --git a/src/coverlet.core/Properties/AssemblyInfo.cs b/src/coverlet.core/Properties/AssemblyInfo.cs index 8eb19aee7..7e65be514 100644 --- a/src/coverlet.core/Properties/AssemblyInfo.cs +++ b/src/coverlet.core/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; using System.Runtime.CompilerServices; diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index e9e13c719..0daff6a69 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Diagnostics; @@ -21,42 +24,42 @@ internal class CoberturaReporter : IReporter public string Report(CoverageResult result, ISourceRootTranslator sourceRootTranslator) { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); - var lineCoverage = summary.CalculateLineCoverage(result.Modules); - var branchCoverage = summary.CalculateBranchCoverage(result.Modules); + CoverageDetails lineCoverage = summary.CalculateLineCoverage(result.Modules); + CoverageDetails branchCoverage = summary.CalculateBranchCoverage(result.Modules); - XDocument xml = new XDocument(); - XElement coverage = new XElement("coverage"); + var xml = new XDocument(); + var coverage = new XElement("coverage"); coverage.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(result.Modules).Percent / 100).ToString(CultureInfo.InvariantCulture))); coverage.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(result.Modules).Percent / 100).ToString(CultureInfo.InvariantCulture))); coverage.Add(new XAttribute("version", "1.9")); coverage.Add(new XAttribute("timestamp", (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds)); - XElement sources = new XElement("sources"); + var sources = new XElement("sources"); - List absolutePaths = new List(); + var absolutePaths = new List(); if (!result.Parameters.DeterministicReport) { absolutePaths = GetBasePaths(result.Modules, result.Parameters.UseSourceLink).ToList(); absolutePaths.ForEach(x => sources.Add(new XElement("source", x))); } - XElement packages = new XElement("packages"); - foreach (var module in result.Modules) + var packages = new XElement("packages"); + foreach (KeyValuePair module in result.Modules) { - XElement package = new XElement("package"); + var package = new XElement("package"); package.Add(new XAttribute("name", Path.GetFileNameWithoutExtension(module.Key))); package.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(module.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); package.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(module.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); package.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(module.Value))); - XElement classes = new XElement("classes"); - foreach (var document in module.Value) + var classes = new XElement("classes"); + foreach (KeyValuePair document in module.Value) { - foreach (var cls in document.Value) + foreach (KeyValuePair cls in document.Value) { - XElement @class = new XElement("class"); + var @class = new XElement("class"); @class.Add(new XAttribute("name", cls.Key)); string fileName; if (!result.Parameters.DeterministicReport) @@ -72,27 +75,27 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran @class.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(cls.Value).Percent / 100).ToString(CultureInfo.InvariantCulture))); @class.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(cls.Value))); - XElement classLines = new XElement("lines"); - XElement methods = new XElement("methods"); + var classLines = new XElement("lines"); + var methods = new XElement("methods"); - foreach (var meth in cls.Value) + foreach (KeyValuePair meth in cls.Value) { // Skip all methods with no lines if (meth.Value.Lines.Count == 0) continue; - XElement method = new XElement("method"); + var method = new XElement("method"); method.Add(new XAttribute("name", meth.Key.Split(':').Last().Split('(').First())); method.Add(new XAttribute("signature", "(" + meth.Key.Split(':').Last().Split('(').Last())); method.Add(new XAttribute("line-rate", (summary.CalculateLineCoverage(meth.Value.Lines).Percent / 100).ToString(CultureInfo.InvariantCulture))); method.Add(new XAttribute("branch-rate", (summary.CalculateBranchCoverage(meth.Value.Branches).Percent / 100).ToString(CultureInfo.InvariantCulture))); method.Add(new XAttribute("complexity", summary.CalculateCyclomaticComplexity(meth.Value.Branches))); - XElement lines = new XElement("lines"); - foreach (var ln in meth.Value.Lines) + var lines = new XElement("lines"); + foreach (KeyValuePair ln in meth.Value.Lines) { bool isBranchPoint = meth.Value.Branches.Any(b => b.Line == ln.Key); - XElement line = new XElement("line"); + var line = new XElement("line"); line.Add(new XAttribute("number", ln.Key.ToString())); line.Add(new XAttribute("hits", ln.Value.ToString())); line.Add(new XAttribute("branch", isBranchPoint.ToString())); @@ -100,13 +103,13 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran if (isBranchPoint) { var branches = meth.Value.Branches.Where(b => b.Line == ln.Key).ToList(); - var branchInfoCoverage = summary.CalculateBranchCoverage(branches); + CoverageDetails branchInfoCoverage = summary.CalculateBranchCoverage(branches); line.Add(new XAttribute("condition-coverage", $"{branchInfoCoverage.Percent.ToString(CultureInfo.InvariantCulture)}% ({branchInfoCoverage.Covered.ToString(CultureInfo.InvariantCulture)}/{branchInfoCoverage.Total.ToString(CultureInfo.InvariantCulture)})")); - XElement conditions = new XElement("conditions"); + var conditions = new XElement("conditions"); var byOffset = branches.GroupBy(b => b.Offset).ToDictionary(b => b.Key, b => b.ToList()); - foreach (var entry in byOffset) + foreach (KeyValuePair> entry in byOffset) { - XElement condition = new XElement("condition"); + var condition = new XElement("condition"); condition.Add(new XAttribute("number", entry.Key)); condition.Add(new XAttribute("type", entry.Value.Count() > 2 ? "switch" : "jump")); // Just guessing here condition.Add(new XAttribute("coverage", $"{summary.CalculateBranchCoverage(entry.Value).Percent.ToString(CultureInfo.InvariantCulture)}%")); @@ -218,7 +221,7 @@ private static string GetRelativePathFromBase(IEnumerable basePaths, str return path; } - foreach (var basePath in basePaths) + foreach (string basePath in basePaths) { if (path.StartsWith(basePath)) { diff --git a/src/coverlet.core/Reporters/JsonReporter.cs b/src/coverlet.core/Reporters/JsonReporter.cs index bbcb4fa31..39ecc6e2f 100644 --- a/src/coverlet.core/Reporters/JsonReporter.cs +++ b/src/coverlet.core/Reporters/JsonReporter.cs @@ -1,7 +1,8 @@ -using Newtonsoft.Json; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. using Coverlet.Core.Abstractions; -using System; +using Newtonsoft.Json; namespace Coverlet.Core.Reporters { @@ -18,4 +19,4 @@ public string Report(CoverageResult result, ISourceRootTranslator _) return JsonConvert.SerializeObject(result.Modules, Formatting.Indented); } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Reporters/LcovReporter.cs b/src/coverlet.core/Reporters/LcovReporter.cs index f1ede2437..5b7471f42 100644 --- a/src/coverlet.core/Reporters/LcovReporter.cs +++ b/src/coverlet.core/Reporters/LcovReporter.cs @@ -1,7 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; -using System.Linq; using System.Collections.Generic; - +using System.Linq; using Coverlet.Core.Abstractions; namespace Coverlet.Core.Reporters @@ -21,21 +23,21 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran throw new NotSupportedException("Deterministic report not supported by lcov reporter"); } - CoverageSummary summary = new CoverageSummary(); - List lcov = new List(); + var summary = new CoverageSummary(); + var lcov = new List(); - foreach (var module in result.Modules) + foreach (KeyValuePair module in result.Modules) { - foreach (var doc in module.Value) + foreach (KeyValuePair doc in module.Value) { - var docLineCoverage = summary.CalculateLineCoverage(doc.Value); - var docBranchCoverage = summary.CalculateBranchCoverage(doc.Value); - var docMethodCoverage = summary.CalculateMethodCoverage(doc.Value); + CoverageDetails docLineCoverage = summary.CalculateLineCoverage(doc.Value); + CoverageDetails docBranchCoverage = summary.CalculateBranchCoverage(doc.Value); + CoverageDetails docMethodCoverage = summary.CalculateMethodCoverage(doc.Value); lcov.Add("SF:" + doc.Key); - foreach (var @class in doc.Value) + foreach (KeyValuePair @class in doc.Value) { - foreach (var method in @class.Value) + foreach (KeyValuePair method in @class.Value) { // Skip all methods with no lines if (method.Value.Lines.Count == 0) @@ -44,10 +46,10 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran lcov.Add($"FN:{method.Value.Lines.First().Key - 1},{method.Key}"); lcov.Add($"FNDA:{method.Value.Lines.First().Value},{method.Key}"); - foreach (var line in method.Value.Lines) + foreach (KeyValuePair line in method.Value.Lines) lcov.Add($"DA:{line.Key},{line.Value}"); - foreach (var branch in method.Value.Branches) + foreach (BranchInfo branch in method.Value.Branches) { lcov.Add($"BRDA:{branch.Line},{branch.Offset},{branch.Path},{branch.Hits}"); } @@ -70,4 +72,4 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran return string.Join(Environment.NewLine, lcov); } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index 6d4c7b6ba..2e42c2894 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -1,10 +1,12 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml.Linq; - using Coverlet.Core.Abstractions; namespace Coverlet.Core.Reporters @@ -24,63 +26,63 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran throw new NotSupportedException("Deterministic report not supported by openCover reporter"); } - CoverageSummary summary = new CoverageSummary(); - XDocument xml = new XDocument(); - XElement coverage = new XElement("CoverageSession"); - XElement coverageSummary = new XElement("Summary"); - XElement modules = new XElement("Modules"); + var summary = new CoverageSummary(); + var xml = new XDocument(); + var coverage = new XElement("CoverageSession"); + var coverageSummary = new XElement("Summary"); + var modules = new XElement("Modules"); int numClasses = 0, numMethods = 0; int visitedClasses = 0, visitedMethods = 0; int i = 1; - foreach (var mod in result.Modules) + foreach (System.Collections.Generic.KeyValuePair mod in result.Modules) { - XElement module = new XElement("Module"); + var module = new XElement("Module"); module.Add(new XAttribute("hash", Guid.NewGuid().ToString().ToUpper())); - XElement path = new XElement("ModulePath", mod.Key); - XElement time = new XElement("ModuleTime", DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss")); - XElement name = new XElement("ModuleName", Path.GetFileNameWithoutExtension(mod.Key)); + var path = new XElement("ModulePath", mod.Key); + var time = new XElement("ModuleTime", DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss")); + var name = new XElement("ModuleName", Path.GetFileNameWithoutExtension(mod.Key)); module.Add(path); module.Add(time); module.Add(name); - XElement files = new XElement("Files"); - XElement classes = new XElement("Classes"); + var files = new XElement("Files"); + var classes = new XElement("Classes"); - foreach (var doc in mod.Value) + foreach (System.Collections.Generic.KeyValuePair doc in mod.Value) { - XElement file = new XElement("File"); + var file = new XElement("File"); file.Add(new XAttribute("uid", i.ToString())); file.Add(new XAttribute("fullPath", doc.Key)); files.Add(file); - foreach (var cls in doc.Value) + foreach (System.Collections.Generic.KeyValuePair cls in doc.Value) { - XElement @class = new XElement("Class"); - XElement classSummary = new XElement("Summary"); + var @class = new XElement("Class"); + var classSummary = new XElement("Summary"); - XElement className = new XElement("FullName", cls.Key); + var className = new XElement("FullName", cls.Key); - XElement methods = new XElement("Methods"); + var methods = new XElement("Methods"); int j = 0; - var classVisited = false; + bool classVisited = false; - foreach (var meth in cls.Value) + foreach (System.Collections.Generic.KeyValuePair meth in cls.Value) { // Skip all methods with no lines if (meth.Value.Lines.Count == 0) continue; - var methLineCoverage = summary.CalculateLineCoverage(meth.Value.Lines); - var methBranchCoverage = summary.CalculateBranchCoverage(meth.Value.Branches); - var methCyclomaticComplexity = summary.CalculateCyclomaticComplexity(meth.Value.Branches); - var methNpathComplexity = summary.CalculateNpathComplexity(meth.Value.Branches); + CoverageDetails methLineCoverage = summary.CalculateLineCoverage(meth.Value.Lines); + CoverageDetails methBranchCoverage = summary.CalculateBranchCoverage(meth.Value.Branches); + int methCyclomaticComplexity = summary.CalculateCyclomaticComplexity(meth.Value.Branches); + int methNpathComplexity = summary.CalculateNpathComplexity(meth.Value.Branches); - XElement method = new XElement("Method"); + var method = new XElement("Method"); method.Add(new XAttribute("cyclomaticComplexity", methCyclomaticComplexity.ToString())); method.Add(new XAttribute("nPathComplexity", methCyclomaticComplexity.ToString())); @@ -91,12 +93,12 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran method.Add(new XAttribute("isSetter", meth.Key.Contains("set_").ToString())); method.Add(new XAttribute("isStatic", (!meth.Key.Contains("get_") || !meth.Key.Contains("set_")).ToString())); - XElement methodName = new XElement("Name", meth.Key); + var methodName = new XElement("Name", meth.Key); - XElement fileRef = new XElement("FileRef"); + var fileRef = new XElement("FileRef"); fileRef.Add(new XAttribute("uid", i.ToString())); - XElement methodPoint = new XElement("MethodPoint"); + var methodPoint = new XElement("MethodPoint"); methodPoint.Add(new XAttribute("vc", methLineCoverage.Covered.ToString())); methodPoint.Add(new XAttribute("uspid", "0")); methodPoint.Add(new XAttribute(XName.Get("type", "xsi"), "SequencePoint")); @@ -111,19 +113,19 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran methodPoint.Add(new XAttribute("fileid", i.ToString())); // They're really just lines - XElement sequencePoints = new XElement("SequencePoints"); - XElement branchPoints = new XElement("BranchPoints"); - XElement methodSummary = new XElement("Summary"); + var sequencePoints = new XElement("SequencePoints"); + var branchPoints = new XElement("BranchPoints"); + var methodSummary = new XElement("Summary"); int k = 0; int kBr = 0; - var methodVisited = false; + bool methodVisited = false; - foreach (var lines in meth.Value.Lines) + foreach (System.Collections.Generic.KeyValuePair lines in meth.Value.Lines) { - var lineBranches = meth.Value.Branches.Where(branchInfo => branchInfo.Line == lines.Key).ToArray(); - var branchCoverage = summary.CalculateBranchCoverage(lineBranches); - - XElement sequencePoint = new XElement("SequencePoint"); + BranchInfo[] lineBranches = meth.Value.Branches.Where(branchInfo => branchInfo.Line == lines.Key).ToArray(); + CoverageDetails branchCoverage = summary.CalculateBranchCoverage(lineBranches); + + var sequencePoint = new XElement("SequencePoint"); sequencePoint.Add(new XAttribute("vc", lines.Value.ToString())); sequencePoint.Add(new XAttribute("uspid", lines.Key.ToString())); sequencePoint.Add(new XAttribute("ordinal", k.ToString())); @@ -145,9 +147,9 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran k++; } - foreach (var branche in meth.Value.Branches) + foreach (BranchInfo branche in meth.Value.Branches) { - XElement branchPoint = new XElement("BranchPoint"); + var branchPoint = new XElement("BranchPoint"); branchPoint.Add(new XAttribute("vc", branche.Hits.ToString())); branchPoint.Add(new XAttribute("uspid", branche.Line.ToString())); branchPoint.Add(new XAttribute("ordinal", branche.Ordinal.ToString())); @@ -192,11 +194,11 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran if (classVisited) visitedClasses++; - var classLineCoverage = summary.CalculateLineCoverage(cls.Value); - var classBranchCoverage = summary.CalculateBranchCoverage(cls.Value); - var classMethodCoverage = summary.CalculateMethodCoverage(cls.Value); - var classMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(cls.Value); - var classMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(cls.Value); + CoverageDetails classLineCoverage = summary.CalculateLineCoverage(cls.Value); + CoverageDetails classBranchCoverage = summary.CalculateBranchCoverage(cls.Value); + CoverageDetails classMethodCoverage = summary.CalculateMethodCoverage(cls.Value); + int classMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(cls.Value); + int classMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(cls.Value); classSummary.Add(new XAttribute("numSequencePoints", classLineCoverage.Total.ToString())); classSummary.Add(new XAttribute("visitedSequencePoints", classLineCoverage.Covered.ToString())); @@ -224,10 +226,10 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran modules.Add(module); } - var moduleLineCoverage = summary.CalculateLineCoverage(result.Modules); - var moduleBranchCoverage = summary.CalculateBranchCoverage(result.Modules); - var moduleMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(result.Modules); - var moduleMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(result.Modules); + CoverageDetails moduleLineCoverage = summary.CalculateLineCoverage(result.Modules); + CoverageDetails moduleBranchCoverage = summary.CalculateBranchCoverage(result.Modules); + int moduleMaxCyclomaticComplexity = summary.CalculateMaxCyclomaticComplexity(result.Modules); + int moduleMinCyclomaticComplexity = summary.CalculateMinCyclomaticComplexity(result.Modules); coverageSummary.Add(new XAttribute("numSequencePoints", moduleLineCoverage.Total.ToString())); coverageSummary.Add(new XAttribute("visitedSequencePoints", moduleLineCoverage.Covered.ToString())); @@ -252,4 +254,4 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran return Encoding.UTF8.GetString(stream.ToArray()); } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Reporters/ReporterFactory.cs b/src/coverlet.core/Reporters/ReporterFactory.cs index 0d13520cb..2c9dc95ee 100644 --- a/src/coverlet.core/Reporters/ReporterFactory.cs +++ b/src/coverlet.core/Reporters/ReporterFactory.cs @@ -1,14 +1,16 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Linq; - using Coverlet.Core.Abstractions; namespace Coverlet.Core.Reporters { internal class ReporterFactory { - private string _format; - private IReporter[] _reporters; + private readonly string _format; + private readonly IReporter[] _reporters; public ReporterFactory(string format) { @@ -28,4 +30,4 @@ public bool IsValidFormat() public IReporter CreateReporter() => _reporters.FirstOrDefault(r => string.Equals(r.Format, _format, StringComparison.OrdinalIgnoreCase)); } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Reporters/TeamCityReporter.cs b/src/coverlet.core/Reporters/TeamCityReporter.cs index acb5d4ff1..365f20e46 100644 --- a/src/coverlet.core/Reporters/TeamCityReporter.cs +++ b/src/coverlet.core/Reporters/TeamCityReporter.cs @@ -1,7 +1,9 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Globalization; using System.Text; - using Coverlet.Core.Abstractions; namespace Coverlet.Core.Reporters @@ -23,9 +25,9 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran // Calculate coverage var summary = new CoverageSummary(); - var overallLineCoverage = summary.CalculateLineCoverage(result.Modules); - var overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules); - var overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules); + CoverageDetails overallLineCoverage = summary.CalculateLineCoverage(result.Modules); + CoverageDetails overallBranchCoverage = summary.CalculateBranchCoverage(result.Modules); + CoverageDetails overallMethodCoverage = summary.CalculateMethodCoverage(result.Modules); // Report coverage var stringBuilder = new StringBuilder(); diff --git a/src/coverlet.core/Symbols/BranchPoint.cs b/src/coverlet.core/Symbols/BranchPoint.cs index 077d569d2..77a675e82 100644 --- a/src/coverlet.core/Symbols/BranchPoint.cs +++ b/src/coverlet.core/Symbols/BranchPoint.cs @@ -1,6 +1,8 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Diagnostics; -using System.Text.RegularExpressions; namespace Coverlet.Core.Symbols { diff --git a/src/coverlet.core/Symbols/CecilSymbolHelper.cs b/src/coverlet.core/Symbols/CecilSymbolHelper.cs index b6727de46..23789124a 100644 --- a/src/coverlet.core/Symbols/CecilSymbolHelper.cs +++ b/src/coverlet.core/Symbols/CecilSymbolHelper.cs @@ -1,12 +1,12 @@ -// -// This class is based heavily on the work of the OpenCover -// team in OpenCover.Framework.Symbols.CecilSymbolManager -// +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; + using Coverlet.Core.Abstractions; using Coverlet.Core.Extensions; @@ -272,10 +272,10 @@ private static bool SkipGeneratedBranchForExceptionRethrown(List in int branchIndex = instructions.BinarySearch(instruction, new InstructionByOffsetComparer()); - return new[] {2,3}.Any(x => branchIndex >= x && - instructions[branchIndex - x].OpCode == OpCodes.Isinst && - instructions[branchIndex - x].Operand is TypeReference tr && - tr.FullName == "System.Exception") + return new[] { 2, 3 }.Any(x => branchIndex >= x && + instructions[branchIndex - x].OpCode == OpCodes.Isinst && + instructions[branchIndex - x].Operand is TypeReference tr && + tr.FullName == "System.Exception") && // check for throw opcode after branch instructions.Count - branchIndex >= 3 && @@ -399,11 +399,11 @@ private bool SkipGeneratedBranchesForExceptionHandlers(MethodDefinition methodDe */ if (!_compilerGeneratedBranchesToExclude.ContainsKey(methodDefinition.FullName)) { - List detectedBranches = new List(); + var detectedBranches = new List(); Collection handlers = methodDefinition.Body.ExceptionHandlers; int numberOfCatchBlocks = 1; - foreach (var handler in handlers) + foreach (ExceptionHandler handler in handlers) { if (handlers.Any(h => h.HandlerStart == handler.HandlerEnd)) { @@ -663,7 +663,7 @@ static bool CheckForSkipDisposal(List instructions, Instruction ins { return false; } - + bool isFollowedByDisposeAsync = false; if (instructions[currentIndex - 1].OpCode == OpCodes.Ldfld && @@ -1021,13 +1021,13 @@ public IReadOnlyList GetBranchPoints(MethodDefinition methodDefinit continue; } - var pathCounter = 0; + int pathCounter = 0; // store branch origin offset - var branchOffset = instruction.Offset; - var closestSeqPt = FindClosestInstructionWithSequencePoint(methodDefinition.Body, instruction).Maybe(i => methodDefinition.DebugInformation.GetSequencePoint(i)); - var branchingInstructionLine = closestSeqPt.Maybe(x => x.StartLine, -1); - var document = closestSeqPt.Maybe(x => x.Document.Url); + int branchOffset = instruction.Offset; + SequencePoint closestSeqPt = FindClosestInstructionWithSequencePoint(methodDefinition.Body, instruction).Maybe(i => methodDefinition.DebugInformation.GetSequencePoint(i)); + int branchingInstructionLine = closestSeqPt.Maybe(x => x.StartLine, -1); + string document = closestSeqPt.Maybe(x => x.Document.Url); if (instruction.Next == null) { @@ -1054,9 +1054,9 @@ private static bool BuildPointsForConditionalBranch(List list, Inst // Add Default branch (Path=0) // Follow else/default instruction - var @else = instruction.Next; + Instruction @else = instruction.Next; - var pathOffsetList = GetBranchPath(@else); + List pathOffsetList = GetBranchPath(@else); // add Path 0 var path0 = new BranchPoint @@ -1077,8 +1077,7 @@ private static bool BuildPointsForConditionalBranch(List list, Inst if (instruction.OpCode.Code != Code.Switch) { // Follow instruction at operand - var @then = instruction.Operand as Instruction; - if (@then == null) + if (instruction.Operand is not Instruction @then) return false; ordinal = BuildPointsForBranch(list, then, branchingInstructionLine, document, branchOffset, @@ -1086,8 +1085,7 @@ private static bool BuildPointsForConditionalBranch(List list, Inst } else // instruction.OpCode.Code == Code.Switch { - var branchInstructions = instruction.Operand as Instruction[]; - if (branchInstructions == null || branchInstructions.Length == 0) + if (instruction.Operand is not Instruction[] branchInstructions || branchInstructions.Length == 0) return false; ordinal = BuildPointsForSwitchCases(list, path0, branchInstructions, branchingInstructionLine, @@ -1099,7 +1097,7 @@ private static bool BuildPointsForConditionalBranch(List list, Inst private static uint BuildPointsForBranch(List list, Instruction then, int branchingInstructionLine, string document, int branchOffset, uint ordinal, int pathCounter, BranchPoint path0, List instructions, MethodDefinition methodDefinition) { - var pathOffsetList1 = GetBranchPath(@then); + List pathOffsetList1 = GetBranchPath(@then); // Add path 1 var path1 = new BranchPoint @@ -1119,7 +1117,7 @@ private static uint BuildPointsForBranch(List list, Instruction the // only add branch if branch does not match a known sequence // e.g. auto generated field assignment // or encapsulates at least one sequence point - var offsets = new[] + int[] offsets = new[] { path0.Offset, path0.EndOffset, @@ -1127,22 +1125,22 @@ private static uint BuildPointsForBranch(List list, Instruction the path1.EndOffset }; - var ignoreSequences = new[] + Code[][] ignoreSequences = new[] { // we may need other samples new[] {Code.Brtrue_S, Code.Pop, Code.Ldsfld, Code.Ldftn, Code.Newobj, Code.Dup, Code.Stsfld, Code.Newobj}, // CachedAnonymousMethodDelegate field allocation }; - var bs = offsets.Min(); - var be = offsets.Max(); + int bs = offsets.Min(); + int be = offsets.Max(); var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList(); - var match = ignoreSequences + bool match = ignoreSequences .Where(ignoreSequence => range.Count >= ignoreSequence.Length) .Any(ignoreSequence => range.Zip(ignoreSequence, (instruction, code) => instruction.OpCode.Code == code).All(x => x)); - var count = range + int count = range .Count(i => methodDefinition.DebugInformation.GetSequencePoint(i) != null); if (!match || count > 0) @@ -1156,7 +1154,7 @@ private static uint BuildPointsForBranch(List list, Instruction the private static uint BuildPointsForSwitchCases(List list, BranchPoint path0, Instruction[] branchInstructions, int branchingInstructionLine, string document, int branchOffset, uint ordinal, ref int pathCounter) { - var counter = pathCounter; + int counter = pathCounter; list.Add(path0); // Add Conditional Branches (Path>0) list.AddRange(branchInstructions.Select(GetBranchPath) @@ -1342,7 +1340,7 @@ instance void .ctor () cil managed } ... */ - var autogeneratedBackingFields = methodDefinition.DeclaringType.Fields.Where(x => + IEnumerable autogeneratedBackingFields = methodDefinition.DeclaringType.Fields.Where(x => x.CustomAttributes.Any(ca => ca.AttributeType.FullName.Equals(typeof(CompilerGeneratedAttribute).FullName)) && x.FullName.EndsWith("k__BackingField")); @@ -1354,15 +1352,15 @@ instance void .ctor () cil managed private static bool SkipDefaultInitializationSystemObject(Instruction instruction) { - /* - A type always has a constructor with a default instantiation of System.Object. For record types these - instructions can have a own sequence point. This means that even the default constructor would be instrumented. - To skip this we search for call instructions with a method reference that declares System.Object. + /* + A type always has a constructor with a default instantiation of System.Object. For record types these + instructions can have a own sequence point. This means that even the default constructor would be instrumented. + To skip this we search for call instructions with a method reference that declares System.Object. - IL_0000: ldarg.0 - IL_0001: call instance void [System.Runtime]System.Object::.ctor() - IL_0006: ret - */ + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ret + */ return instruction.OpCode == OpCodes.Ldarg && instruction.Next?.OpCode == OpCodes.Call && instruction.Next?.Operand is MethodReference mr && mr.DeclaringType.FullName.Equals(typeof(System.Object).FullName); @@ -1378,7 +1376,7 @@ private static bool SkipBranchGeneratedExceptionFilter(Instruction branchInstruc .Where(e => e.HandlerType == ExceptionHandlerType.Filter) .ToList(); - foreach (var exceptionHandler in handlers) + foreach (ExceptionHandler exceptionHandler in handlers) { Instruction startFilter = exceptionHandler.FilterStart; Instruction endFilter = startFilter; @@ -1418,7 +1416,7 @@ private static bool SkipBranchGeneratedFinallyBlock(Instruction branchInstructio private static int GetOffsetOfNextEndfinally(MethodBody body, int startOffset) { - var lastOffset = body.Instructions.LastOrDefault().Maybe(i => i.Offset, int.MaxValue); + int lastOffset = body.Instructions.LastOrDefault().Maybe(i => i.Offset, int.MaxValue); return body.Instructions.FirstOrDefault(i => i.Offset >= startOffset && i.OpCode.Code == Code.Endfinally).Maybe(i => i.Offset, lastOffset); } @@ -1428,12 +1426,11 @@ private static List GetBranchPath(Instruction instruction) if (instruction != null) { - var point = instruction; + Instruction point = instruction; offsetList.Add(point.Offset); while (point.OpCode == OpCodes.Br || point.OpCode == OpCodes.Br_S) { - var nextPoint = point.Operand as Instruction; - if (nextPoint != null) + if (point.Operand is Instruction nextPoint) { point = nextPoint; offsetList.Add(point.Offset); @@ -1453,12 +1450,12 @@ private static Instruction FindClosestInstructionWithSequencePoint(MethodBody me var sequencePointsInMethod = methodBody.Instructions.Where(i => HasValidSequencePoint(i, methodBody.Method)).ToList(); if (!sequencePointsInMethod.Any()) return null; - var idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetComparer()); + int idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetComparer()); Instruction prev; if (idx < 0) { // no exact match, idx corresponds to the next, larger element - var lower = Math.Max(~idx - 1, 0); + int lower = Math.Max(~idx - 1, 0); prev = sequencePointsInMethod[lower]; } else @@ -1472,7 +1469,7 @@ private static Instruction FindClosestInstructionWithSequencePoint(MethodBody me private static bool HasValidSequencePoint(Instruction instruction, MethodDefinition methodDefinition) { - var sp = methodDefinition.DebugInformation.GetSequencePoint(instruction); + SequencePoint sp = methodDefinition.DebugInformation.GetSequencePoint(instruction); return sp != null && sp.StartLine != StepOverLineCode; } diff --git a/src/coverlet.msbuild.tasks/BaseTask.cs b/src/coverlet.msbuild.tasks/BaseTask.cs index 1cf3aa6ce..99606bda8 100644 --- a/src/coverlet.msbuild.tasks/BaseTask.cs +++ b/src/coverlet.msbuild.tasks/BaseTask.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using Microsoft.Build.Utilities; namespace Coverlet.MSbuild.Tasks diff --git a/src/coverlet.msbuild.tasks/CoverageResultTask.cs b/src/coverlet.msbuild.tasks/CoverageResultTask.cs index ebc17a0e4..642d2a92b 100644 --- a/src/coverlet.msbuild.tasks/CoverageResultTask.cs +++ b/src/coverlet.msbuild.tasks/CoverageResultTask.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Globalization; @@ -17,7 +20,7 @@ namespace Coverlet.MSbuild.Tasks { public class CoverageResultTask : BaseTask { - private MSBuildLogger _logger; + private readonly MSBuildLogger _logger; [Required] public string Output { get; set; } @@ -63,11 +66,11 @@ public override bool Execute() Coverage coverage = null; using (Stream instrumenterStateStream = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open)) { - var instrumentationHelper = ServiceProvider.GetService(); + IInstrumentationHelper instrumentationHelper = ServiceProvider.GetService(); // Task.Log is teared down after a task and thus the new MSBuildLogger must be passed to the InstrumentationHelper // https://github.com/microsoft/msbuild/issues/5153 instrumentationHelper.SetLogger(_logger); - coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), this._logger, ServiceProvider.GetService(), fileSystem, ServiceProvider.GetService()); + coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), _logger, ServiceProvider.GetService(), fileSystem, ServiceProvider.GetService()); } try @@ -82,7 +85,7 @@ public override bool Execute() CoverageResult result = coverage.GetCoverageResult(); - var directory = Path.GetDirectoryName(Output); + string directory = Path.GetDirectoryName(Output); if (directory == string.Empty) { directory = Directory.GetCurrentDirectory(); @@ -92,12 +95,12 @@ public override bool Execute() Directory.CreateDirectory(directory); } - var formats = OutputFormat.Split(','); + string[] formats = OutputFormat.Split(','); var coverageReportPaths = new List(formats.Length); ISourceRootTranslator sourceRootTranslator = ServiceProvider.GetService(); - foreach (var format in formats) + foreach (string format in formats) { - var reporter = new ReporterFactory(format).CreateReporter(); + IReporter reporter = new ReporterFactory(format).CreateReporter(); if (reporter == null) { throw new Exception($"Specified output format '{format}' is not supported"); @@ -119,7 +122,7 @@ public override bool Execute() ServiceProvider.GetService(), result, sourceRootTranslator); - var path = writer.WriteReport(); + string path = writer.WriteReport(); var metadata = new Dictionary { ["Format"] = format }; coverageReportPaths.Add(new TaskItem(path, metadata)); } @@ -129,7 +132,7 @@ public override bool Execute() var thresholdTypeFlagQueue = new Queue(); - foreach (var thresholdType in ThresholdType.Split(',').Select(t => t.Trim())) + foreach (string thresholdType in ThresholdType.Split(',').Select(t => t.Trim())) { if (thresholdType.Equals("line", StringComparison.OrdinalIgnoreCase)) { @@ -144,19 +147,19 @@ public override bool Execute() thresholdTypeFlagQueue.Enqueue(ThresholdTypeFlags.Method); } } - - Dictionary thresholdTypeFlagValues = new Dictionary(); + + var thresholdTypeFlagValues = new Dictionary(); if (Threshold.Contains(',')) { - var thresholdValues = Threshold.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()); - if(thresholdValues.Count() != thresholdTypeFlagQueue.Count()) + IEnumerable thresholdValues = Threshold.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()); + if (thresholdValues.Count() != thresholdTypeFlagQueue.Count()) { throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count()}) and values count ({thresholdValues.Count()}) doesn't match"); } - foreach (var threshold in thresholdValues) + foreach (string threshold in thresholdValues) { - if (double.TryParse(threshold, out var value)) + if (double.TryParse(threshold, out double value)) { thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = value; } @@ -175,8 +178,8 @@ public override bool Execute() thresholdTypeFlagValues[thresholdTypeFlagQueue.Dequeue()] = thresholdValue; } } - - var thresholdStat = ThresholdStatistic.Minimum; + + ThresholdStatistic thresholdStat = ThresholdStatistic.Minimum; if (ThresholdStat.Equals("average", StringComparison.OrdinalIgnoreCase)) { thresholdStat = ThresholdStatistic.Average; @@ -189,23 +192,23 @@ public override bool Execute() var coverageTable = new ConsoleTable("Module", "Line", "Branch", "Method"); var summary = new CoverageSummary(); - var linePercentCalculation = summary.CalculateLineCoverage(result.Modules); - var branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); - var methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); + CoverageDetails linePercentCalculation = summary.CalculateLineCoverage(result.Modules); + CoverageDetails branchPercentCalculation = summary.CalculateBranchCoverage(result.Modules); + CoverageDetails methodPercentCalculation = summary.CalculateMethodCoverage(result.Modules); - var totalLinePercent = linePercentCalculation.Percent; - var totalBranchPercent = branchPercentCalculation.Percent; - var totalMethodPercent = methodPercentCalculation.Percent; + double totalLinePercent = linePercentCalculation.Percent; + double totalBranchPercent = branchPercentCalculation.Percent; + double totalMethodPercent = methodPercentCalculation.Percent; - var averageLinePercent = linePercentCalculation.AverageModulePercent; - var averageBranchPercent = branchPercentCalculation.AverageModulePercent; - var averageMethodPercent = methodPercentCalculation.AverageModulePercent; + double averageLinePercent = linePercentCalculation.AverageModulePercent; + double averageBranchPercent = branchPercentCalculation.AverageModulePercent; + double averageMethodPercent = methodPercentCalculation.AverageModulePercent; - foreach (var module in result.Modules) + foreach (KeyValuePair module in result.Modules) { - var linePercent = summary.CalculateLineCoverage(module.Value).Percent; - var branchPercent = summary.CalculateBranchCoverage(module.Value).Percent; - var methodPercent = summary.CalculateMethodCoverage(module.Value).Percent; + double linePercent = summary.CalculateLineCoverage(module.Value).Percent; + double branchPercent = summary.CalculateBranchCoverage(module.Value).Percent; + double methodPercent = summary.CalculateMethodCoverage(module.Value).Percent; coverageTable.AddRow(Path.GetFileNameWithoutExtension(module.Key), $"{InvariantFormat(linePercent)}%", $"{InvariantFormat(branchPercent)}%", $"{InvariantFormat(methodPercent)}%"); } @@ -222,7 +225,7 @@ public override bool Execute() Console.WriteLine(coverageTable.ToStringAlternative()); - var thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStat); + ThresholdTypeFlags thresholdTypeFlags = result.GetThresholdTypesBelowThreshold(summary, thresholdTypeFlagValues, thresholdStat); if (thresholdTypeFlags != ThresholdTypeFlags.None) { var exceptionMessageBuilder = new StringBuilder(); diff --git a/src/coverlet.msbuild.tasks/InstrumentationTask.cs b/src/coverlet.msbuild.tasks/InstrumentationTask.cs index 9be72b5c6..e84327dd0 100644 --- a/src/coverlet.msbuild.tasks/InstrumentationTask.cs +++ b/src/coverlet.msbuild.tasks/InstrumentationTask.cs @@ -1,7 +1,9 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Diagnostics; using System.IO; - using Coverlet.Core; using Coverlet.Core.Abstractions; using Coverlet.Core.Helpers; @@ -9,6 +11,7 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Microsoft.Extensions.DependencyInjection; + using ILogger = Coverlet.Core.Abstractions.ILogger; namespace Coverlet.MSbuild.Tasks @@ -81,9 +84,9 @@ public override bool Execute() try { - var fileSystem = ServiceProvider.GetService(); + IFileSystem fileSystem = ServiceProvider.GetService(); - CoverageParameters parameters = new CoverageParameters + var parameters = new CoverageParameters { IncludeFilters = Include?.Split(','), IncludeDirectories = IncludeDirectory?.Split(','), @@ -99,7 +102,7 @@ public override bool Execute() DoesNotReturnAttributes = DoesNotReturnAttribute?.Split(',') }; - Coverage coverage = new Coverage(Path, + var coverage = new Coverage(Path, parameters, _logger, ServiceProvider.GetService(), @@ -109,7 +112,7 @@ public override bool Execute() CoveragePrepareResult prepareResult = coverage.PrepareModules(); InstrumenterState = new TaskItem(System.IO.Path.GetTempFileName()); - using (var instrumentedStateFile = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write)) + using (Stream instrumentedStateFile = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write)) { using (Stream serializedState = CoveragePrepareResult.Serialize(prepareResult)) { diff --git a/src/coverlet.msbuild.tasks/MSBuildLogger.cs b/src/coverlet.msbuild.tasks/MSBuildLogger.cs index e35f0af82..33fe3afaf 100644 --- a/src/coverlet.msbuild.tasks/MSBuildLogger.cs +++ b/src/coverlet.msbuild.tasks/MSBuildLogger.cs @@ -1,5 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using ILogger = Coverlet.Core.Abstractions.ILogger; diff --git a/src/coverlet.msbuild.tasks/Properties/AssemblyInfo.cs b/src/coverlet.msbuild.tasks/Properties/AssemblyInfo.cs index 944948378..4ff5754c3 100644 --- a/src/coverlet.msbuild.tasks/Properties/AssemblyInfo.cs +++ b/src/coverlet.msbuild.tasks/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; using System.Runtime.CompilerServices; diff --git a/src/coverlet.msbuild.tasks/ReportWriter.cs b/src/coverlet.msbuild.tasks/ReportWriter.cs index 1261ce76c..8b72b9767 100644 --- a/src/coverlet.msbuild.tasks/ReportWriter.cs +++ b/src/coverlet.msbuild.tasks/ReportWriter.cs @@ -1,8 +1,9 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.IO; using Coverlet.Core; using Coverlet.Core.Abstractions; -using Coverlet.Core.Reporters; namespace Coverlet.MSbuild.Tasks { diff --git a/test/coverlet.collector.tests/AttachmentManagerTests.cs b/test/coverlet.collector.tests/AttachmentManagerTests.cs index 9adb4c731..9e021212d 100644 --- a/test/coverlet.collector.tests/AttachmentManagerTests.cs +++ b/test/coverlet.collector.tests/AttachmentManagerTests.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.ComponentModel; using System.IO; using Microsoft.VisualStudio.TestPlatform.ObjectModel; @@ -14,14 +17,14 @@ namespace Coverlet.Collector.Tests public class AttachmentManagerTests { private AttachmentManager _attachmentManager; - private Mock _mockDataCollectionSink; - private DataCollectionContext _dataCollectionContext; - private TestPlatformLogger _testPlatformLogger; - private TestPlatformEqtTrace _eqtTrace; - private Mock _mockFileHelper; - private Mock _mockDirectoryHelper; - private Mock _mockCountDownEvent; - private Mock _mockDataCollectionLogger; + private readonly Mock _mockDataCollectionSink; + private readonly DataCollectionContext _dataCollectionContext; + private readonly TestPlatformLogger _testPlatformLogger; + private readonly TestPlatformEqtTrace _eqtTrace; + private readonly Mock _mockFileHelper; + private readonly Mock _mockDirectoryHelper; + private readonly Mock _mockCountDownEvent; + private readonly Mock _mockDataCollectionLogger; public AttachmentManagerTests() { @@ -71,7 +74,7 @@ public void SendCoverageReportShouldThrowExceptionWhenFailedToSaveReportToFile() [Fact] public void SendCoverageReportShouldSendAttachmentToTestPlatform() { - var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); + DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); _attachmentManager = new AttachmentManager(_mockDataCollectionSink.Object, _dataCollectionContext, _testPlatformLogger, _eqtTrace, directory.ToString(), new FileHelper(), _mockDirectoryHelper.Object, _mockCountDownEvent.Object); diff --git a/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs b/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs index 3c0346d20..66fb8bd67 100644 --- a/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs +++ b/test/coverlet.collector.tests/CoverletCoverageDataCollectorTests.cs @@ -1,9 +1,11 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; using Moq; using Microsoft.VisualStudio.TestPlatform.ObjectModel; @@ -22,15 +24,15 @@ namespace Coverlet.Collector.Tests { public class CoverletCoverageDataCollectorTests { - private DataCollectionEnvironmentContext _context; + private readonly DataCollectionEnvironmentContext _context; private CoverletCoverageCollector _coverletCoverageDataCollector; - private DataCollectionContext _dataCollectionContext; - private Mock _mockDataColectionEvents; - private Mock _mockDataCollectionSink; - private Mock _mockCoverageWrapper; - private Mock _mockCountDownEventFactory; + private readonly DataCollectionContext _dataCollectionContext; + private readonly Mock _mockDataColectionEvents; + private readonly Mock _mockDataCollectionSink; + private readonly Mock _mockCoverageWrapper; + private readonly Mock _mockCountDownEventFactory; private XmlElement _configurationElement; - private Mock _mockLogger; + private readonly Mock _mockLogger; public CoverletCoverageDataCollectorTests() { @@ -39,7 +41,7 @@ public CoverletCoverageDataCollectorTests() _mockLogger = new Mock(); _configurationElement = null; - TestCase testcase = new TestCase { Id = Guid.NewGuid() }; + var testcase = new TestCase { Id = Guid.NewGuid() }; _dataCollectionContext = new DataCollectionContext(testcase); _context = new DataCollectionEnvironmentContext(_dataCollectionContext); _mockCoverageWrapper = new Mock(); @@ -53,7 +55,7 @@ public void OnSessionStartShouldInitializeCoverageWithCorrectCoverletSettings() Func serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) => { IServiceCollection serviceCollection = new ServiceCollection(); - Mock fileSystem = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string testLib) => testLib == "abc.dll"); serviceCollection.AddTransient(_ => fileSystem.Object); @@ -87,7 +89,7 @@ public void OnSessionStartShouldPrepareModulesForCoverage() Func serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) => { IServiceCollection serviceCollection = new ServiceCollection(); - Mock fileSystem = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string testLib) => testLib == "abc.dll"); serviceCollection.AddTransient(_ => fileSystem.Object); @@ -114,7 +116,7 @@ public void OnSessionStartShouldPrepareModulesForCoverage() new Mock().Object, new Mock().Object); - CoverageParameters parameters = new CoverageParameters + var parameters = new CoverageParameters { IncludeFilters = null, IncludeDirectories = null, @@ -126,7 +128,7 @@ public void OnSessionStartShouldPrepareModulesForCoverage() UseSourceLink = true }; - Coverage coverage = new Coverage("abc.dll", parameters, It.IsAny(), instrumentationHelper, new Mock().Object, new Mock().Object, new Mock().Object); + var coverage = new Coverage("abc.dll", parameters, It.IsAny(), instrumentationHelper, new Mock().Object, new Mock().Object, new Mock().Object); sessionStartProperties.Add("TestSources", new List { "abc.dll" }); _mockCoverageWrapper.Setup(x => x.CreateCoverage(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(coverage); @@ -163,7 +165,7 @@ public void OnSessionEndShouldSendGetCoverageReportToTestPlatform() string module = GetType().Assembly.Location; string pdb = Path.Combine(Path.GetDirectoryName(module), Path.GetFileNameWithoutExtension(module) + ".pdb"); - var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); + DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); File.Copy(module, Path.Combine(directory.FullName, Path.GetFileName(module)), true); File.Copy(pdb, Path.Combine(directory.FullName, Path.GetFileName(pdb)), true); @@ -188,7 +190,7 @@ public void OnSessionEndShouldSendCoverageReportsForMultipleFormatsToTestPlatfor Func serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) => { IServiceCollection serviceCollection = new ServiceCollection(); - Mock fileSystem = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string testLib) => testLib == "Test"); serviceCollection.AddTransient(_ => fileSystem.Object); @@ -203,7 +205,7 @@ public void OnSessionEndShouldSendCoverageReportsForMultipleFormatsToTestPlatfor _coverletCoverageDataCollector = new CoverletCoverageCollector(new TestPlatformEqtTrace(), new CoverageWrapper(), _mockCountDownEventFactory.Object, serviceCollectionFactory); IList reporters = formats.Split(',').Select(f => new ReporterFactory(f).CreateReporter()).Where(x => x != null).ToList(); - Mock mockDataCollectionSink = new Mock(); + var mockDataCollectionSink = new Mock(); mockDataCollectionSink.Setup(m => m.SendFileAsync(It.IsAny())).Callback(fti => { reporters.Remove(reporters.First(x => @@ -212,8 +214,8 @@ public void OnSessionEndShouldSendCoverageReportsForMultipleFormatsToTestPlatfor }); var doc = new XmlDocument(); - var root = doc.CreateElement("Configuration"); - var element = doc.CreateElement("Format"); + XmlElement root = doc.CreateElement("Configuration"); + XmlElement element = doc.CreateElement("Format"); element.AppendChild(doc.CreateTextNode(formats)); root.AppendChild(element); @@ -241,7 +243,7 @@ public void OnSessionStartShouldLogWarningIfInstrumentationFailed() Func serviceCollectionFactory = (TestPlatformEqtTrace eqtTrace, TestPlatformLogger logger, string testModule) => { IServiceCollection serviceCollection = new ServiceCollection(); - Mock fileSystem = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string testLib) => testLib == "abc.dll"); serviceCollection.AddTransient(_ => fileSystem.Object); diff --git a/test/coverlet.collector.tests/CoverletSettingsParserTests.cs b/test/coverlet.collector.tests/CoverletSettingsParserTests.cs index ebcba0b3f..0e3286e06 100644 --- a/test/coverlet.collector.tests/CoverletSettingsParserTests.cs +++ b/test/coverlet.collector.tests/CoverletSettingsParserTests.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; using System.Linq; using System.Xml; using Coverlet.Collector.DataCollection; @@ -9,7 +12,7 @@ namespace Coverlet.Collector.Tests { public class CoverletSettingsParserTests { - private CoverletSettingsParser _coverletSettingsParser; + private readonly CoverletSettingsParser _coverletSettingsParser; public CoverletSettingsParserTests() { @@ -64,19 +67,19 @@ public void ParseShouldCorrectlyParseConfigurationElement(string includeFilters, { var testModules = new List { "abc.dll" }; var doc = new XmlDocument(); - var configElement = doc.CreateElement("Configuration"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName, includeFilters); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName, excludeFilters); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName, includeDirectories); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName, excludeSourceFiles); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName, excludeAttributes); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.MergeWithElementName, "/path/to/result.json"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.UseSourceLinkElementName, "false"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.SingleHitElementName, "true"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeTestAssemblyElementName, "true"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.SkipAutoProps, "true"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.DeterministicReport, "true"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.DoesNotReturnAttributesElementName, doesNotReturnAttributes); + XmlElement configElement = doc.CreateElement("Configuration"); + CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName, includeFilters); + CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName, excludeFilters); + CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName, includeDirectories); + CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName, excludeSourceFiles); + CreateCoverletNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName, excludeAttributes); + CreateCoverletNodes(doc, configElement, CoverletConstants.MergeWithElementName, "/path/to/result.json"); + CreateCoverletNodes(doc, configElement, CoverletConstants.UseSourceLinkElementName, "false"); + CreateCoverletNodes(doc, configElement, CoverletConstants.SingleHitElementName, "true"); + CreateCoverletNodes(doc, configElement, CoverletConstants.IncludeTestAssemblyElementName, "true"); + CreateCoverletNodes(doc, configElement, CoverletConstants.SkipAutoProps, "true"); + CreateCoverletNodes(doc, configElement, CoverletConstants.DeterministicReport, "true"); + CreateCoverletNodes(doc, configElement, CoverletConstants.DoesNotReturnAttributesElementName, doesNotReturnAttributes); CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules); @@ -109,12 +112,12 @@ public void ParseShouldCorrectlyParseConfigurationElementWithNullInnerText() { var testModules = new List { "abc.dll" }; var doc = new XmlDocument(); - var configElement = doc.CreateElement("Configuration"); - this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName); - this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName); - this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName); - this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName); - this.CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName); + XmlElement configElement = doc.CreateElement("Configuration"); + CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeFiltersElementName); + CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeFiltersElementName); + CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.IncludeDirectoriesElementName); + CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeSourceFilesElementName); + CreateCoverletNullInnerTextNodes(doc, configElement, CoverletConstants.ExcludeAttributesElementName); CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules); @@ -131,7 +134,7 @@ public void ParseShouldCorrectlyParseConfigurationElementWithNullElements() { var testModules = new List { "abc.dll" }; var doc = new XmlDocument(); - var configElement = doc.CreateElement("Configuration"); + XmlElement configElement = doc.CreateElement("Configuration"); CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules); @@ -160,8 +163,8 @@ public void ParseShouldCorrectlyParseMultipleFormats(string formats, int formats { var testModules = new List { "abc.dll" }; var doc = new XmlDocument(); - var configElement = doc.CreateElement("Configuration"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats); + XmlElement configElement = doc.CreateElement("Configuration"); + CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats); CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules); @@ -175,10 +178,10 @@ public void ParseShouldCorrectlyParseMultipleFormats(string formats, int formats public void ParseShouldUseDefaultFormatWhenNoFormatSpecified(string formats) { var testModules = new List { "abc.dll" }; - var defaultFormat = CoverletConstants.DefaultReportFormat; + string defaultFormat = CoverletConstants.DefaultReportFormat; var doc = new XmlDocument(); - var configElement = doc.CreateElement("Configuration"); - this.CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats); + XmlElement configElement = doc.CreateElement("Configuration"); + CreateCoverletNodes(doc, configElement, CoverletConstants.ReportFormatElementName, formats); CoverletSettings coverletSettings = _coverletSettingsParser.Parse(configElement, testModules); @@ -187,14 +190,14 @@ public void ParseShouldUseDefaultFormatWhenNoFormatSpecified(string formats) private void CreateCoverletNodes(XmlDocument doc, XmlElement configElement, string nodeSetting, string nodeValue) { - var node = doc.CreateNode("element", nodeSetting, string.Empty); + XmlNode node = doc.CreateNode("element", nodeSetting, string.Empty); node.InnerText = nodeValue; configElement.AppendChild(node); } private void CreateCoverletNullInnerTextNodes(XmlDocument doc, XmlElement configElement, string nodeSetting) { - var node = doc.CreateNode("element", nodeSetting, string.Empty); + XmlNode node = doc.CreateNode("element", nodeSetting, string.Empty); node.InnerText = null; configElement.AppendChild(node); } diff --git a/test/coverlet.collector.tests/Properties/AssemblyInfo.cs b/test/coverlet.collector.tests/Properties/AssemblyInfo.cs index b80d4b319..0d10a5c3c 100644 --- a/test/coverlet.collector.tests/Properties/AssemblyInfo.cs +++ b/test/coverlet.collector.tests/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; [assembly: AssemblyKeyFile("coverlet.collector.tests.snk")] diff --git a/test/coverlet.core.performancetest/.editorconfig b/test/coverlet.core.performancetest/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.core.performancetest/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.core.tests.samples.netstandard/.editorconfig b/test/coverlet.core.tests.samples.netstandard/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.core.tests.samples.netstandard/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.core.tests/Coverage/CoverageSummaryTests.cs b/test/coverlet.core.tests/Coverage/CoverageSummaryTests.cs index d66b72573..1a04e2021 100644 --- a/test/coverlet.core.tests/Coverage/CoverageSummaryTests.cs +++ b/test/coverlet.core.tests/Coverage/CoverageSummaryTests.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using Coverlet.Core; -using Moq; +using System.Linq; using Xunit; namespace Coverlet.Core.Tests @@ -23,29 +21,29 @@ public CoverageSummaryTests() private void SetupDataForArithmeticPrecision() { - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); for (int i = 2; i <= 6; i++) { lines.Add(i, 0); } - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 }); for (int i = 2; i <= 6; i++) { branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 1, Path = 1, Ordinal = (uint)i }); } - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Tests.CoverageSummaryTests", methods); - Documents documents = new Documents(); + var documents = new Documents(); documents.Add("doc.cs", classes); _moduleArithmeticPrecision = new Modules(); @@ -54,23 +52,23 @@ private void SetupDataForArithmeticPrecision() private void SetupDataSingleModule() { - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 0); - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 }); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 1, Ordinal = 2 }); - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Tests.CoverageSummaryTests", methods); - Documents documents = new Documents(); + var documents = new Documents(); documents.Add("doc.cs", classes); _averageCalculationSingleModule = new Modules(); @@ -79,21 +77,21 @@ private void SetupDataSingleModule() private void SetupDataMultipleModule() { - Lines lines = new Lines + var lines = new Lines { { 1, 1 }, // covered { 2, 0 }, // not covered { 3, 0 } // not covered }; - Branches branches = new Branches + var branches = new Branches { new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 }, // covered new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 1, Ordinal = 2 }, // covered new BranchInfo { Line = 1, Hits = 0, Offset = 1, Path = 1, Ordinal = 2 } // not covered }; - Methods methods = new Methods(); + var methods = new Methods(); string[] methodString = { "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()", // covered "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestAditionalCalculateSummary()" // not covered @@ -108,12 +106,12 @@ private void SetupDataMultipleModule() { 1, 0 } // not covered }; - Classes classes = new Classes + var classes = new Classes { { "Coverlet.Core.Tests.CoverageSummaryTests", methods } }; - Documents documents = new Documents + var documents = new Documents { { "doc.cs", classes } }; @@ -128,7 +126,7 @@ private void SetupDataMultipleModule() [Fact] public void TestCalculateLineCoverage_NoModules() { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); var modules = new Modules(); Assert.Equal(0, summary.CalculateLineCoverage(modules).Percent); @@ -142,12 +140,12 @@ public void TestCalculateLineCoverage_NoModules() [Fact] public void TestCalculateLineCoverage_SingleModule() { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); - var module = _averageCalculationSingleModule.First(); - var document = module.Value.First(); - var @class = document.Value.First(); - var method = @class.Value.First(); + System.Collections.Generic.KeyValuePair module = _averageCalculationSingleModule.First(); + System.Collections.Generic.KeyValuePair document = module.Value.First(); + System.Collections.Generic.KeyValuePair @class = document.Value.First(); + System.Collections.Generic.KeyValuePair method = @class.Value.First(); Assert.Equal(50, summary.CalculateLineCoverage(_averageCalculationSingleModule).AverageModulePercent); Assert.Equal(50, summary.CalculateLineCoverage(module.Value).Percent); @@ -159,9 +157,9 @@ public void TestCalculateLineCoverage_SingleModule() [Fact] public void TestCalculateLineCoverage_MultiModule() { - CoverageSummary summary = new CoverageSummary(); - var documentsFirstModule = _averageCalculationMultiModule["module"]; - var documentsSecondModule = _averageCalculationMultiModule["aditionalModule"]; + var summary = new CoverageSummary(); + Documents documentsFirstModule = _averageCalculationMultiModule["module"]; + Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"]; Assert.Equal(37.5, summary.CalculateLineCoverage(_averageCalculationMultiModule).AverageModulePercent); Assert.Equal(50, summary.CalculateLineCoverage(documentsFirstModule.First().Value).Percent); @@ -174,12 +172,12 @@ public void TestCalculateLineCoverage_MultiModule() [Fact] public void TestCalculateBranchCoverage_SingleModule() { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); - var module = _averageCalculationSingleModule.First(); - var document = module.Value.First(); - var @class = document.Value.First(); - var method = @class.Value.First(); + System.Collections.Generic.KeyValuePair module = _averageCalculationSingleModule.First(); + System.Collections.Generic.KeyValuePair document = module.Value.First(); + System.Collections.Generic.KeyValuePair @class = document.Value.First(); + System.Collections.Generic.KeyValuePair method = @class.Value.First(); Assert.Equal(100, summary.CalculateBranchCoverage(_averageCalculationSingleModule).AverageModulePercent); Assert.Equal(100, summary.CalculateBranchCoverage(module.Value).Percent); @@ -191,9 +189,9 @@ public void TestCalculateBranchCoverage_SingleModule() [Fact] public void TestCalculateBranchCoverage_MultiModule() { - CoverageSummary summary = new CoverageSummary(); - var documentsFirstModule = _averageCalculationMultiModule["module"]; - var documentsSecondModule = _averageCalculationMultiModule["aditionalModule"]; + var summary = new CoverageSummary(); + Documents documentsFirstModule = _averageCalculationMultiModule["module"]; + Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"]; Assert.Equal(83.33, summary.CalculateBranchCoverage(_averageCalculationMultiModule).AverageModulePercent); Assert.Equal(100, summary.CalculateBranchCoverage(documentsFirstModule.First().Value).Percent); @@ -203,12 +201,12 @@ public void TestCalculateBranchCoverage_MultiModule() [Fact] public void TestCalculateMethodCoverage_SingleModule() { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); - var module = _averageCalculationSingleModule.First(); - var document = module.Value.First(); - var @class = document.Value.First(); - var method = @class.Value.First(); + System.Collections.Generic.KeyValuePair module = _averageCalculationSingleModule.First(); + System.Collections.Generic.KeyValuePair document = module.Value.First(); + System.Collections.Generic.KeyValuePair @class = document.Value.First(); + System.Collections.Generic.KeyValuePair method = @class.Value.First(); Assert.Equal(100, summary.CalculateMethodCoverage(_averageCalculationSingleModule).AverageModulePercent); Assert.Equal(100, summary.CalculateMethodCoverage(module.Value).Percent); @@ -220,9 +218,9 @@ public void TestCalculateMethodCoverage_SingleModule() [Fact] public void TestCalculateMethodCoverage_MultiModule() { - CoverageSummary summary = new CoverageSummary(); - var documentsFirstModule = _averageCalculationMultiModule["module"]; - var documentsSecondModule = _averageCalculationMultiModule["aditionalModule"]; + var summary = new CoverageSummary(); + Documents documentsFirstModule = _averageCalculationMultiModule["module"]; + Documents documentsSecondModule = _averageCalculationMultiModule["aditionalModule"]; Assert.Equal(75, summary.CalculateMethodCoverage(_averageCalculationMultiModule).AverageModulePercent); Assert.Equal(100, summary.CalculateMethodCoverage(documentsFirstModule.First().Value).Percent); @@ -232,12 +230,12 @@ public void TestCalculateMethodCoverage_MultiModule() [Fact] public void TestCalculateLineCoveragePercentage_ArithmeticPrecisionCheck() { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); - var module = _moduleArithmeticPrecision.First(); - var document = module.Value.First(); - var @class = document.Value.First(); - var method = @class.Value.First(); + System.Collections.Generic.KeyValuePair module = _moduleArithmeticPrecision.First(); + System.Collections.Generic.KeyValuePair document = module.Value.First(); + System.Collections.Generic.KeyValuePair @class = document.Value.First(); + System.Collections.Generic.KeyValuePair method = @class.Value.First(); Assert.Equal(16.66, summary.CalculateLineCoverage(_moduleArithmeticPrecision).AverageModulePercent); Assert.Equal(16.66, summary.CalculateLineCoverage(module.Value).Percent); @@ -249,12 +247,12 @@ public void TestCalculateLineCoveragePercentage_ArithmeticPrecisionCheck() [Fact] public void TestCalculateBranchCoveragePercentage_ArithmeticPrecisionCheck() { - CoverageSummary summary = new CoverageSummary(); + var summary = new CoverageSummary(); - var module = _moduleArithmeticPrecision.First(); - var document = module.Value.First(); - var @class = document.Value.First(); - var method = @class.Value.First(); + System.Collections.Generic.KeyValuePair module = _moduleArithmeticPrecision.First(); + System.Collections.Generic.KeyValuePair document = module.Value.First(); + System.Collections.Generic.KeyValuePair @class = document.Value.First(); + System.Collections.Generic.KeyValuePair method = @class.Value.First(); Assert.Equal(16.66, summary.CalculateBranchCoverage(_moduleArithmeticPrecision).AverageModulePercent); Assert.Equal(16.66, summary.CalculateBranchCoverage(module.Value).Percent); @@ -263,4 +261,4 @@ public void TestCalculateBranchCoveragePercentage_ArithmeticPrecisionCheck() Assert.Equal(16.66, summary.CalculateBranchCoverage(method.Value.Branches).Percent); } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwait.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwait.cs index 40d733b7f..e127c1660 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwait.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwait.cs @@ -1,10 +1,10 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests @@ -146,7 +146,7 @@ public void AsyncAwait_Issue_1177() return 0; }, new string[] { path }); - var document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs"); + Core.Instrumentation.Document document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs"); document.AssertLinesCovered(BuildConfiguration.Debug, (133, 1), (134, 1), (135, 1), (136, 1), (137, 1)); Assert.DoesNotContain(document.Branches, x => x.Key.Line == 134); } @@ -174,7 +174,7 @@ public void AsyncAwait_Issue_1233() return 0; }, new string[] { path }); - var document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs"); + Core.Instrumentation.Document document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs"); document.AssertLinesCovered(BuildConfiguration.Debug, (150, 1)); Assert.DoesNotContain(document.Branches, x => x.Key.Line == 150); } @@ -203,7 +203,7 @@ public void AsyncAwait_Issue_1275() return 0; }, new string[] { path }); - var document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs"); + Core.Instrumentation.Document document = TestInstrumentationHelper.GetCoverageResult(path).Document("Instrumentation.AsyncAwait.cs"); document.AssertLinesCoveredFromTo(BuildConfiguration.Debug, 170, 176); document.AssertBranchesCovered(BuildConfiguration.Debug, (171, 0, 1), (171, 1, 1)); Assert.DoesNotContain(document.Branches, x => x.Key.Line == 176); @@ -214,4 +214,4 @@ public void AsyncAwait_Issue_1275() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwaitValueTask.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwaitValueTask.cs index 0438dc66d..dc7ebddfc 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwaitValueTask.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncAwaitValueTask.cs @@ -1,8 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs index abeee16cd..8e3a2bc91 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Linq; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncIterator.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncIterator.cs index 67aa6b323..a14157c42 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncIterator.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncIterator.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AutoProps.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AutoProps.cs index 8b923da86..134a61bad 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AutoProps.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AutoProps.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; using System.Threading.Tasks; using Coverlet.Core.Samples.Tests; using Xunit; diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AwaitUsing.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AwaitUsing.cs index a5849090f..82bab4694 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AwaitUsing.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AwaitUsing.cs @@ -1,8 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.CatchBlock.cs b/test/coverlet.core.tests/Coverage/CoverageTests.CatchBlock.cs index 9c356b968..fc6e1cb13 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.CatchBlock.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.CatchBlock.cs @@ -1,8 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests @@ -64,7 +65,7 @@ public void CatchBlock_Issue465() return 0; }, new string[] { path }); - var res = TestInstrumentationHelper.GetCoverageResult(path); + CoverageResult res = TestInstrumentationHelper.GetCoverageResult(path); res.Document("Instrumentation.CatchBlock.cs") .AssertLinesCoveredAllBut(BuildConfiguration.Debug, 45, 59, 113, 127, 137, 138, 139, 153, 154, 155, 156, 175, 189, 199, 200, 201, 222, 223, 224, 225, 252, 266, 335, 349) .ExpectedTotalNumberOfBranches(BuildConfiguration.Debug, 6) @@ -76,4 +77,4 @@ public void CatchBlock_Issue465() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.DoesNotReturn.cs b/test/coverlet.core.tests/Coverage/CoverageTests.DoesNotReturn.cs index 67219a6ec..e5950232a 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.DoesNotReturn.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.DoesNotReturn.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.IO; using System.Threading.Tasks; using Coverlet.Core.Samples.Tests; diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs b/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs index 6f75f76da..e989c3838 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs @@ -1,14 +1,14 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Threading.Tasks; - using Coverlet.Core.Abstractions; using Coverlet.Core.Helpers; using Coverlet.Core.Samples.Tests; using Coverlet.Core.Symbols; -using Coverlet.Tests.Xunit.Extensions; using Moq; using Xunit; @@ -19,7 +19,7 @@ public partial class CoverageTests [Fact] public void TestCoverageSkipModule__AssemblyMarkedAsExcludeFromCodeCoverage() { - Mock partialMockFileSystem = new Mock(); + var partialMockFileSystem = new Mock(); partialMockFileSystem.CallBase = true; partialMockFileSystem.Setup(fs => fs.NewFileStream(It.IsAny(), It.IsAny(), It.IsAny())).Returns((string path, FileMode mode, FileAccess access) => { @@ -29,11 +29,11 @@ public void TestCoverageSkipModule__AssemblyMarkedAsExcludeFromCodeCoverage() string excludedbyattributeDll = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "TestAssets"), "coverlet.tests.projectsample.excludedbyattribute.dll").First(); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(excludedbyattributeDll, new Mock().Object, new FileSystem())); - CoverageParameters parameters = new CoverageParameters + var parameters = new CoverageParameters { IncludeFilters = new string[] { "[coverlet.tests.projectsample.excludedbyattribute*]*" }, IncludeDirectories = Array.Empty(), @@ -74,7 +74,7 @@ public void ExcludeFromCodeCoverage_CompilerGeneratedMethodsAndTypes() CoverageResult result = TestInstrumentationHelper.GetCoverageResult(path); - var document = result.Document("Instrumentation.ExcludeFromCoverage.cs"); + Core.Instrumentation.Document document = result.Document("Instrumentation.ExcludeFromCoverage.cs"); // Invoking method "Test" of class "MethodsWithExcludeFromCodeCoverageAttr" we expect to cover 100% lines for MethodsWithExcludeFromCodeCoverageAttr Assert.DoesNotContain(document.Lines, l => @@ -278,4 +278,4 @@ public void ExcludeFromCodeCoverageAutoGeneratedGet() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.Filters.cs b/test/coverlet.core.tests/Coverage/CoverageTests.Filters.cs index 2845d5c1c..e86e61a3f 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.Filters.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.Filters.cs @@ -1,10 +1,11 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.IO; using System.Reflection; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests @@ -128,4 +129,4 @@ public void ExcludeFilteredNestedTypes() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.IntegerOverflow.cs b/test/coverlet.core.tests/Coverage/CoverageTests.IntegerOverflow.cs index 5b9121f81..5e206fa34 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.IntegerOverflow.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.IntegerOverflow.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; using Coverlet.Core.Abstractions; using Coverlet.Core.Instrumentation; using Moq; @@ -11,7 +14,7 @@ public partial class CoverageTests [Fact] public void CoverageResult_NegativeLineCoverage_TranslatedToMaxValueOfInt32() { - InstrumenterResult instrumenterResult = new InstrumenterResult + var instrumenterResult = new InstrumenterResult { HitsFilePath = "HitsFilePath", SourceLink = "SourceLink", @@ -36,7 +39,7 @@ public void CoverageResult_NegativeLineCoverage_TranslatedToMaxValueOfInt32() instrumenterResult.Documents.Add("document", document); - CoveragePrepareResult coveragePrepareResult = new CoveragePrepareResult + var coveragePrepareResult = new CoveragePrepareResult { UseSourceLink = true, Results = new[] {instrumenterResult}, @@ -44,7 +47,7 @@ public void CoverageResult_NegativeLineCoverage_TranslatedToMaxValueOfInt32() }; Stream memoryStream = new MemoryStream(); - BinaryWriter binaryWriter = new BinaryWriter(memoryStream); + var binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(1); binaryWriter.Write(-1); memoryStream.Position = 0; @@ -57,7 +60,7 @@ public void CoverageResult_NegativeLineCoverage_TranslatedToMaxValueOfInt32() var coverage = new Coverage(coveragePrepareResult, new Mock().Object, new Mock().Object, fileSystemMock.Object, new Mock().Object); - var coverageResult = coverage.GetCoverageResult(); + CoverageResult coverageResult = coverage.GetCoverageResult(); coverageResult.Document("document").AssertLinesCovered(BuildConfiguration.Debug, (1, int.MaxValue)); } diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.Lambda.cs b/test/coverlet.core.tests/Coverage/CoverageTests.Lambda.cs index 37b3e76aa..24a87a681 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.Lambda.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.Lambda.cs @@ -1,8 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests @@ -138,4 +139,4 @@ public void Issue_1056() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.SelectionStatements.cs b/test/coverlet.core.tests/Coverage/CoverageTests.SelectionStatements.cs index 367b9b592..3e551daf7 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.SelectionStatements.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.SelectionStatements.cs @@ -1,8 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Threading.Tasks; - using Coverlet.Core.Samples.Tests; -using Coverlet.Tests.Xunit.Extensions; using Tmds.Utils; using Xunit; @@ -150,4 +151,4 @@ public void SelectionStatements_Switch_CSharp8_AllBranches() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.Yield.cs b/test/coverlet.core.tests/Coverage/CoverageTests.Yield.cs index f2aca5360..e491d9003 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.Yield.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.Yield.cs @@ -1,6 +1,8 @@ -using System.IO; -using System.Threading.Tasks; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.IO; +using System.Threading.Tasks; using Coverlet.Core.Samples.Tests; using Tmds.Utils; using Xunit; @@ -19,7 +21,7 @@ public void Yield_Single() { CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run(instance => { - foreach (var _ in instance.One()) ; + foreach (dynamic _ in instance.One()) ; return Task.CompletedTask; }, persistPrepareResultToFile: pathSerialize[0]); @@ -50,7 +52,7 @@ public void Yield_Two() { CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run(instance => { - foreach (var _ in instance.Two()) ; + foreach (dynamic _ in instance.Two()) ; return Task.CompletedTask; }, persistPrepareResultToFile: pathSerialize[0]); @@ -80,7 +82,7 @@ public void Yield_SingleWithSwitch() { CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run(instance => { - foreach (var _ in instance.OneWithSwitch(2)) ; + foreach (dynamic _ in instance.OneWithSwitch(2)) ; return Task.CompletedTask; }, persistPrepareResultToFile: pathSerialize[0]); @@ -111,7 +113,7 @@ public void Yield_Three() { CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run(instance => { - foreach (var _ in instance.Three()) ; + foreach (dynamic _ in instance.Three()) ; return Task.CompletedTask; }, persistPrepareResultToFile: pathSerialize[0]); @@ -141,7 +143,7 @@ public void Yield_Enumerable() { CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run(instance => { - foreach (var _ in instance.Enumerable(new[] { "one", "two", "three", "four" })) ; + foreach (dynamic _ in instance.Enumerable(new[] { "one", "two", "three", "four" })) ; return Task.CompletedTask; }, persistPrepareResultToFile: pathSerialize[0]); diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.cs b/test/coverlet.core.tests/Coverage/CoverageTests.cs index 10074bab3..e6bf461eb 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.cs @@ -1,6 +1,8 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.IO; - using Coverlet.Core.Abstractions; using Coverlet.Core.Helpers; using Coverlet.Core.Symbols; @@ -19,17 +21,17 @@ public void TestCoverage() string module = GetType().Assembly.Location; string pdb = Path.Combine(Path.GetDirectoryName(module), Path.GetFileNameWithoutExtension(module) + ".pdb"); - var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); + DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); File.Copy(module, Path.Combine(directory.FullName, Path.GetFileName(module)), true); File.Copy(pdb, Path.Combine(directory.FullName, Path.GetFileName(pdb)), true); // TODO: Find a way to mimick hits - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(module, new Mock().Object, new FileSystem())); - CoverageParameters parameters = new CoverageParameters + var parameters = new CoverageParameters { IncludeFilters = new string[] { "[coverlet.tests.projectsample.excludedbyattribute*]*" }, IncludeDirectories = Array.Empty(), @@ -45,7 +47,7 @@ public void TestCoverage() var coverage = new Coverage(Path.Combine(directory.FullName, Path.GetFileName(module)), parameters, _mockLogger.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(_mockLogger.Object, new FileSystem()), new CecilSymbolHelper()); coverage.PrepareModules(); - var result = coverage.GetCoverageResult(); + CoverageResult result = coverage.GetCoverageResult(); Assert.Empty(result.Modules); @@ -58,16 +60,16 @@ public void TestCoverageWithTestAssembly() string module = GetType().Assembly.Location; string pdb = Path.Combine(Path.GetDirectoryName(module), Path.GetFileNameWithoutExtension(module) + ".pdb"); - var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); + DirectoryInfo directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); File.Copy(module, Path.Combine(directory.FullName, Path.GetFileName(module)), true); File.Copy(pdb, Path.Combine(directory.FullName, Path.GetFileName(pdb)), true); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(module, new Mock().Object, new FileSystem())); - CoverageParameters parameters = new CoverageParameters + var parameters = new CoverageParameters { IncludeFilters = Array.Empty(), IncludeDirectories = Array.Empty(), @@ -84,11 +86,11 @@ public void TestCoverageWithTestAssembly() new SourceRootTranslator(module, _mockLogger.Object, new FileSystem()), new CecilSymbolHelper()); coverage.PrepareModules(); - var result = coverage.GetCoverageResult(); + CoverageResult result = coverage.GetCoverageResult(); Assert.NotEmpty(result.Modules); directory.Delete(true); } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Coverage/InstrumenterHelper.Assertions.cs b/test/coverlet.core.tests/Coverage/InstrumenterHelper.Assertions.cs index 07f3e2bad..24f567312 100644 --- a/test/coverlet.core.tests/Coverage/InstrumenterHelper.Assertions.cs +++ b/test/coverlet.core.tests/Coverage/InstrumenterHelper.Assertions.cs @@ -1,10 +1,12 @@ -using Coverlet.Core.Instrumentation; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Coverlet.Core.Instrumentation; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Xunit.Sdk; @@ -90,18 +92,18 @@ public static Document Method(this Document document, string methodName) if (document.Lines.Values.All(l => l.Method != methodName) && document.Branches.Values.All(l => l.Method != methodName)) { - var methods = document.Lines.Values.Select(l => $"'{l.Method}'") + IEnumerable methods = document.Lines.Values.Select(l => $"'{l.Method}'") .Concat(document.Branches.Values.Select(b => $"'{b.Method}'")) .Distinct(); throw new XunitException($"Method '{methodName}' not found. Methods in document: {string.Join(", ", methods)}"); } - foreach (var line in document.Lines.Where(l => l.Value.Method == methodName)) + foreach (KeyValuePair line in document.Lines.Where(l => l.Value.Method == methodName)) { methodDoc.Lines[line.Key] = line.Value; } - foreach (var branch in document.Branches.Where(b => b.Value.Method == methodName)) + foreach (KeyValuePair branch in document.Branches.Where(b => b.Value.Method == methodName)) { methodDoc.Branches[branch.Key] = branch.Value; } @@ -150,7 +152,7 @@ public static string ToStringBranches(this Document document) throw new ArgumentNullException(nameof(document)); } - StringBuilder builder = new StringBuilder(); + var builder = new StringBuilder(); foreach (KeyValuePair branch in document.Branches) { builder.AppendLine($"({branch.Value.Number}, {branch.Value.Ordinal}, {branch.Value.Hits}),"); @@ -172,7 +174,7 @@ public static Document AssertBranchesCovered(this Document document, BuildConfig return document; } - List branchesToCover = new List(lines.Select(b => $"[line {b.line} ordinal {b.ordinal}]")); + var branchesToCover = new List(lines.Select(b => $"[line {b.line} ordinal {b.ordinal}]")); foreach (KeyValuePair branch in document.Branches) { foreach ((int lineToCheck, int ordinalToCheck, int expectedHits) in lines) @@ -270,7 +272,7 @@ public static Document AssertLinesCoveredFromTo(this Document document, BuildCon throw new ArgumentException("to cannot be lower than from"); } - List lines = new List(); + var lines = new List(); foreach (KeyValuePair line in document.Lines) { if (line.Value.Number >= from && line.Value.Number <= to && line.Value.Hits > 0) @@ -301,7 +303,7 @@ public static Document AssertLinesCovered(this Document document, BuildConfigura return document; } - List linesToCover = new List(lines.Select(l => l.line)); + var linesToCover = new List(lines.Select(l => l.line)); foreach (KeyValuePair line in document.Lines) { foreach ((int lineToCheck, int expectedHits) in lines) @@ -349,7 +351,7 @@ private static Document AssertLinesCoveredInternal(this Document document, Build return document; } - List linesToCover = new List(lines); + var linesToCover = new List(lines); foreach (KeyValuePair line in document.Lines) { foreach (int lineToCheck in lines) @@ -409,7 +411,7 @@ public static Document AssertNonInstrumentedLines(this Document document, BuildC return document; } - var unexpectedlyInstrumented = document.Lines.Select(l => l.Value.Number).Intersect(lines); + IEnumerable unexpectedlyInstrumented = document.Lines.Select(l => l.Value.Number).Intersect(lines); if (unexpectedlyInstrumented.Any()) { @@ -435,7 +437,7 @@ public static Document AssertInstrumentLines(this Document document, BuildConfig var instrumentedLines = document.Lines.Select(l => l.Value.Number).ToHashSet(); - var missing = lines.Where(l => !instrumentedLines.Contains(l)); + IEnumerable missing = lines.Where(l => !instrumentedLines.Contains(l)); if (missing.Any()) { diff --git a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs index 65365163a..efc0138a8 100644 --- a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs +++ b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -28,7 +31,7 @@ static class TestInstrumentationHelper /// public static void GenerateHtmlReport(CoverageResult coverageResult, IReporter reporter = null, string sourceFileFilter = "", [CallerMemberName] string directory = "") { - JsonReporter defaultReporter = new JsonReporter(); + var defaultReporter = new JsonReporter(); reporter ??= new CoberturaReporter(); DirectoryInfo dir = Directory.CreateDirectory(directory); dir.Delete(true); @@ -62,12 +65,12 @@ public static CoverageResult GetCoverageResult(string filePath) Assert.DoesNotContain("not found for module: ", message); }); _processWideContainer.GetRequiredService().SetLogger(logger.Object); - CoveragePrepareResult coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result); - Coverage coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, _processWideContainer.GetService(), new FileSystem(), new SourceRootTranslator(new Mock().Object, new FileSystem())); + var coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result); + var coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, _processWideContainer.GetService(), new FileSystem(), new SourceRootTranslator(new Mock().Object, new FileSystem())); return coverage.GetCoverageResult(); } - async public static Task Run(Func callMethod, + public static async Task Run(Func callMethod, Func includeFilter = null, Func excludeFilter = null, Func doesNotReturnAttributes = null, @@ -93,7 +96,7 @@ async public static Task Run(Func callM static string[] defaultFilters(string _) => Array.Empty(); - CoverageParameters parameters = new CoverageParameters + var parameters = new CoverageParameters { IncludeFilters = (includeFilter is null ? defaultFilters(fileName) : includeFilter(fileName)).Concat( new string[] @@ -117,14 +120,14 @@ async public static Task Run(Func callM }; // Instrument module - Coverage coverage = new Coverage(newPath, parameters, new Logger(logFile), + var coverage = new Coverage(newPath, parameters, new Logger(logFile), _processWideContainer.GetService(), _processWideContainer.GetService(), _processWideContainer.GetService(), _processWideContainer.GetService()); CoveragePrepareResult prepareResult = coverage.PrepareModules(); Assert.Single(prepareResult.Results); // Load new assembly - Assembly asm = Assembly.LoadFile(newPath); + var asm = Assembly.LoadFile(newPath); // Instance type and call method await callMethod(Activator.CreateInstance(asm.GetType(typeof(T).FullName))); @@ -140,7 +143,7 @@ async public static Task Run(Func callM tracker.GetTypeInfo().GetMethod("UnloadModule").Invoke(null, new object[2] { null, null }); // Persist CoveragePrepareResult - using (FileStream fs = new FileStream(persistPrepareResultToFile, FileMode.Open)) + using (var fs = new FileStream(persistPrepareResultToFile, FileMode.Open)) { await CoveragePrepareResult.Serialize(prepareResult).CopyToAsync(fs); } @@ -237,7 +240,7 @@ public void Retry(Action action, Func backoffStrategy, int maxAttemptC // We log to files for debugging pourpose, we can check if instrumentation is ok class Logger : ILogger { - string _logFile; + readonly string _logFile; public Logger(string logFile) => _logFile = logFile; diff --git a/test/coverlet.core.tests/CoverageResultTests.cs b/test/coverlet.core.tests/CoverageResultTests.cs index d391ac45c..fd5450909 100644 --- a/test/coverlet.core.tests/CoverageResultTests.cs +++ b/test/coverlet.core.tests/CoverageResultTests.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; using Coverlet.Core.Enums; using Xunit; @@ -6,22 +9,22 @@ namespace Coverlet.Core.Tests { public class CoverageResultTests { - private Modules _modules; + private readonly Modules _modules; public CoverageResultTests() { - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 1); lines.Add(3, 1); - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 0, Ordinal = 1 }); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 1, Path = 1, Ordinal = 2 }); branches.Add(new BranchInfo { Line = 2, Hits = 0, Offset = 1, Path = 0, Ordinal = 1 }); // System.Void Coverlet.Core.Tests.CoverageResultTests::CoverageResultTests - 3/3 100% line 2/3 66.7% branch coverage - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Tests.CoverageResultTests::CoverageResultTests()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Tests.CoverageResultTests::CoverageResultTests()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; @@ -35,13 +38,13 @@ public CoverageResultTests() {2, 0}, }; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Tests.CoverageResultTests", methods); // Methods - 1/2 (50%) // Lines - 3/5 (60%) // Branches - 2/3 (66.67%) - Documents documents = new Documents(); + var documents = new Documents(); documents.Add("doc.cs", classes); _modules = new Modules(); @@ -51,11 +54,11 @@ public CoverageResultTests() [Fact] public void TestGetThresholdTypesBelowThresholdLine() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Modules = _modules; - CoverageSummary summary = new CoverageSummary(); - Dictionary thresholdTypeFlagValues = new Dictionary() + var summary = new CoverageSummary(); + var thresholdTypeFlagValues = new Dictionary() { { ThresholdTypeFlags.Line, 90 }, { ThresholdTypeFlags.Method, 10 }, @@ -71,11 +74,11 @@ public void TestGetThresholdTypesBelowThresholdLine() [Fact] public void TestGetThresholdTypesBelowThresholdMethod() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Modules = _modules; - CoverageSummary summary = new CoverageSummary(); - Dictionary thresholdTypeFlagValues = new Dictionary() + var summary = new CoverageSummary(); + var thresholdTypeFlagValues = new Dictionary() { { ThresholdTypeFlags.Line, 50 }, { ThresholdTypeFlags.Method, 75 }, @@ -91,11 +94,11 @@ public void TestGetThresholdTypesBelowThresholdMethod() [Fact] public void TestGetThresholdTypesBelowThresholdBranch() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Modules = _modules; - CoverageSummary summary = new CoverageSummary(); - Dictionary thresholdTypeFlagValues = new Dictionary() + var summary = new CoverageSummary(); + var thresholdTypeFlagValues = new Dictionary() { { ThresholdTypeFlags.Line, 50 }, { ThresholdTypeFlags.Method, 50 }, @@ -111,11 +114,11 @@ public void TestGetThresholdTypesBelowThresholdBranch() [Fact] public void TestGetThresholdTypesBelowThresholdAllGood() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Modules = _modules; - CoverageSummary summary = new CoverageSummary(); - Dictionary thresholdTypeFlagValues = new Dictionary() + var summary = new CoverageSummary(); + var thresholdTypeFlagValues = new Dictionary() { { ThresholdTypeFlags.Line, 50 }, { ThresholdTypeFlags.Method, 50 }, @@ -131,11 +134,11 @@ public void TestGetThresholdTypesBelowThresholdAllGood() [Fact] public void TestGetThresholdTypesBelowThresholdAllFail() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Modules = _modules; - CoverageSummary summary = new CoverageSummary(); - Dictionary thresholdTypeFlagValues = new Dictionary() + var summary = new CoverageSummary(); + var thresholdTypeFlagValues = new Dictionary() { { ThresholdTypeFlags.Line, 100 }, { ThresholdTypeFlags.Method, 100 }, @@ -152,11 +155,11 @@ public void TestGetThresholdTypesBelowThresholdAllFail() [Fact] public void TestGetThresholdTypesBelowThresholdWhenNoModuleInstrumented() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Modules = new Modules(); - CoverageSummary summary = new CoverageSummary(); - Dictionary thresholdTypeFlagValues = new Dictionary() + var summary = new CoverageSummary(); + var thresholdTypeFlagValues = new Dictionary() { { ThresholdTypeFlags.Line, 80 }, { ThresholdTypeFlags.Method, 80 }, @@ -170,4 +173,4 @@ public void TestGetThresholdTypesBelowThresholdWhenNoModuleInstrumented() Assert.Equal(thresholdTypeFlags, resThresholdTypeFlags); } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Helpers/FileSystemTests.cs b/test/coverlet.core.tests/Helpers/FileSystemTests.cs index 618a94f89..10f4aa289 100644 --- a/test/coverlet.core.tests/Helpers/FileSystemTests.cs +++ b/test/coverlet.core.tests/Helpers/FileSystemTests.cs @@ -1,4 +1,6 @@ -using Coverlet.Core.Helpers; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using Xunit; namespace Coverlet.Core.Helpers.Tests @@ -12,7 +14,7 @@ public class FileSystemTests [InlineData("filename{T}.cs", "filename{{T}}.cs")] public void TestEscapeFileName(string fileName, string expected) { - var actual = FileSystem.EscapeFileName(fileName); + string actual = FileSystem.EscapeFileName(fileName); Assert.Equal(expected, actual); } diff --git a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs index 745009c72..031b8a5d0 100644 --- a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs +++ b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.IO; using Xunit; @@ -18,7 +21,7 @@ public class InstrumentationHelperTests public void TestGetDependencies() { string module = typeof(InstrumentationHelperTests).Assembly.Location; - var modules = _instrumentationHelper.GetCoverableModules(module, Array.Empty(), false); + string[] modules = _instrumentationHelper.GetCoverableModules(module, Array.Empty(), false); Assert.False(Array.Exists(modules, m => m == module)); } @@ -26,7 +29,7 @@ public void TestGetDependencies() public void TestGetDependenciesWithTestAssembly() { string module = typeof(InstrumentationHelperTests).Assembly.Location; - var modules = _instrumentationHelper.GetCoverableModules(module, Array.Empty(), true); + string[] modules = _instrumentationHelper.GetCoverableModules(module, Array.Empty(), true); Assert.True(Array.Exists(modules, m => m == module)); } @@ -36,7 +39,7 @@ public void EmbeddedPortablePDPHasLocalSource_DocumentDoesNotExist_ReturnsFalse( var fileSystem = new Mock {CallBase = true}; fileSystem.Setup(x => x.Exists(It.IsAny())).Returns(false); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), fileSystem.Object, new Mock().Object, new SourceRootTranslator(typeof(InstrumentationHelperTests).Assembly.Location, new Mock().Object, new FileSystem())); Assert.False(instrumentationHelper.PortablePdbHasLocalSource(typeof(InstrumentationHelperTests).Assembly.Location, out string notFoundDocument)); @@ -65,7 +68,7 @@ public void TestBackupOriginalModule() _instrumentationHelper.BackupOriginalModule(module, identifier); - var backupPath = Path.Combine( + string backupPath = Path.Combine( Path.GetTempPath(), Path.GetFileNameWithoutExtension(module) + "_" + identifier + ".dll" ); @@ -91,7 +94,7 @@ public void TestIsValidFilterExpression() [Fact] public void TestDeleteHitsFile() { - var tempFile = Path.GetTempFileName(); + string tempFile = Path.GetTempFileName(); Assert.True(File.Exists(tempFile)); _instrumentationHelper.DeleteHitsFile(tempFile); @@ -101,7 +104,7 @@ public void TestDeleteHitsFile() [Fact] public void TestIsModuleExcludedWithoutFilter() { - var result = _instrumentationHelper.IsModuleExcluded("Module.dll", new string[0]); + bool result = _instrumentationHelper.IsModuleExcluded("Module.dll", new string[0]); Assert.False(result); } @@ -109,7 +112,7 @@ public void TestIsModuleExcludedWithoutFilter() [Fact] public void TestIsModuleIncludedWithoutFilter() { - var result = _instrumentationHelper.IsModuleIncluded("Module.dll", new string[0]); + bool result = _instrumentationHelper.IsModuleIncluded("Module.dll", new string[0]); Assert.True(result); } @@ -119,7 +122,7 @@ public void TestIsModuleIncludedWithoutFilter() [InlineData("[Mismatch]*")] public void TestIsModuleExcludedWithSingleMismatchFilter(string filter) { - var result = _instrumentationHelper.IsModuleExcluded("Module.dll", new[] { filter }); + bool result = _instrumentationHelper.IsModuleExcluded("Module.dll", new[] { filter }); Assert.False(result); } @@ -127,7 +130,7 @@ public void TestIsModuleExcludedWithSingleMismatchFilter(string filter) [Fact] public void TestIsModuleIncludedWithSingleMismatchFilter() { - var result = _instrumentationHelper.IsModuleIncluded("Module.dll", new[] { "[Mismatch]*" }); + bool result = _instrumentationHelper.IsModuleIncluded("Module.dll", new[] { "[Mismatch]*" }); Assert.False(result); } @@ -136,7 +139,7 @@ public void TestIsModuleIncludedWithSingleMismatchFilter() [MemberData(nameof(ValidModuleFilterData))] public void TestIsModuleExcludedAndIncludedWithFilter(string filter) { - var result = _instrumentationHelper.IsModuleExcluded("Module.dll", new[] { filter }); + bool result = _instrumentationHelper.IsModuleExcluded("Module.dll", new[] { filter }); Assert.True(result); result = _instrumentationHelper.IsModuleIncluded("Module.dll", new[] { filter }); @@ -147,9 +150,9 @@ public void TestIsModuleExcludedAndIncludedWithFilter(string filter) [MemberData(nameof(ValidModuleFilterData))] public void TestIsModuleExcludedAndIncludedWithMatchingAndMismatchingFilter(string filter) { - var filters = new[] { "[Mismatch]*", filter, "[Mismatch]*" }; + string[] filters = new[] { "[Mismatch]*", filter, "[Mismatch]*" }; - var result = _instrumentationHelper.IsModuleExcluded("Module.dll", filters); + bool result = _instrumentationHelper.IsModuleExcluded("Module.dll", filters); Assert.True(result); result = _instrumentationHelper.IsModuleIncluded("Module.dll", filters); @@ -159,7 +162,7 @@ public void TestIsModuleExcludedAndIncludedWithMatchingAndMismatchingFilter(stri [Fact] public void TestIsTypeExcludedWithoutFilter() { - var result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", new string[0]); + bool result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", new string[0]); Assert.False(result); } @@ -167,7 +170,7 @@ public void TestIsTypeExcludedWithoutFilter() [Fact] public void TestIsTypeExcludedNamespace() { - var result = _instrumentationHelper.IsTypeExcluded("Module.dll", "Namespace.Namespace.Type", new string[] { "[Module]Namespace.Namespace.*" }); + bool result = _instrumentationHelper.IsTypeExcluded("Module.dll", "Namespace.Namespace.Type", new string[] { "[Module]Namespace.Namespace.*" }); Assert.True(result); result = _instrumentationHelper.IsTypeExcluded("Module.dll", "Namespace.Namespace.TypeB", new string[] { "[Module]Namespace.Namespace.*" }); @@ -183,7 +186,7 @@ public void TestIsTypeExcludedNamespace() [Fact] public void TestIsTypeIncludedWithoutFilter() { - var result = _instrumentationHelper.IsTypeIncluded("Module.dll", "a.b.Dto", new string[0]); + bool result = _instrumentationHelper.IsTypeIncluded("Module.dll", "a.b.Dto", new string[0]); Assert.True(result); } @@ -194,7 +197,7 @@ public void TestIsTypeIncludedWithoutFilter() [InlineData("[Mismatch]a.b.Dto")] public void TestIsTypeExcludedAndIncludedWithSingleMismatchFilter(string filter) { - var result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", new[] { filter }); + bool result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", new[] { filter }); Assert.False(result); result = _instrumentationHelper.IsTypeIncluded("Module.dll", "a.b.Dto", new[] { filter }); @@ -205,7 +208,7 @@ public void TestIsTypeExcludedAndIncludedWithSingleMismatchFilter(string filter) [MemberData(nameof(ValidModuleAndNamespaceFilterData))] public void TestIsTypeExcludedAndIncludedWithFilter(string filter) { - var result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", new[] { filter }); + bool result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", new[] { filter }); Assert.True(result); result = _instrumentationHelper.IsTypeIncluded("Module.dll", "a.b.Dto", new[] { filter }); @@ -216,9 +219,9 @@ public void TestIsTypeExcludedAndIncludedWithFilter(string filter) [MemberData(nameof(ValidModuleAndNamespaceFilterData))] public void TestIsTypeExcludedAndIncludedWithMatchingAndMismatchingFilter(string filter) { - var filters = new[] { "[Mismatch]*", filter, "[Mismatch]*" }; + string[] filters = new[] { "[Mismatch]*", filter, "[Mismatch]*" }; - var result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", filters); + bool result = _instrumentationHelper.IsTypeExcluded("Module.dll", "a.b.Dto", filters); Assert.True(result); result = _instrumentationHelper.IsTypeIncluded("Module.dll", "a.b.Dto", filters); @@ -241,11 +244,11 @@ public void TestIncludeDirectories() File.Copy("coverlet.msbuild.tasks.dll", Path.Combine(newDir.FullName, "coverlet.msbuild.tasks.dll")); File.Copy("coverlet.core.dll", Path.Combine(newDir2.FullName, "coverlet.core.dll")); - var currentDirModules = _instrumentationHelper.GetCoverableModules(module, Array.Empty(), false); + string[] currentDirModules = _instrumentationHelper.GetCoverableModules(module, Array.Empty(), false); Assert.Single(currentDirModules); Assert.Equal("coverlet.msbuild.tasks.dll", Path.GetFileName(currentDirModules[0])); - var moreThanOneDirectory = _instrumentationHelper + string[] moreThanOneDirectory = _instrumentationHelper .GetCoverableModules(module, new string[] { newDir2.FullName }, false) .OrderBy(f => f).ToArray(); @@ -253,7 +256,7 @@ public void TestIncludeDirectories() Assert.Equal("coverlet.msbuild.tasks.dll", Path.GetFileName(moreThanOneDirectory[0])); Assert.Equal("coverlet.core.dll", Path.GetFileName(moreThanOneDirectory[1])); - var moreThanOneDirectoryPlusTestAssembly = _instrumentationHelper + string[] moreThanOneDirectoryPlusTestAssembly = _instrumentationHelper .GetCoverableModules(module, new string[] { newDir2.FullName }, true) .OrderBy(f => f).ToArray(); @@ -290,5 +293,3 @@ public void TestIncludeDirectories() .Concat(ValidModuleFilterData); } } - - diff --git a/test/coverlet.core.tests/Helpers/RetryHelperTests.cs b/test/coverlet.core.tests/Helpers/RetryHelperTests.cs index 93ce3359c..acbcbd41f 100644 --- a/test/coverlet.core.tests/Helpers/RetryHelperTests.cs +++ b/test/coverlet.core.tests/Helpers/RetryHelperTests.cs @@ -1,5 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using Xunit; namespace Coverlet.Core.Helpers.Tests @@ -28,7 +30,7 @@ public void TestRetryWithFixedRetryBackoff() [Fact] public void TestRetryWithExponentialRetryBackoff() { - var currentSleep = 6; + int currentSleep = 6; Func retryStrategy = () => { var sleep = TimeSpan.FromMilliseconds(currentSleep); @@ -77,4 +79,4 @@ public void TargetActionThrows5Times() if (Calls < 6) throw new Exception("Simulating Failure"); } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Helpers/SourceRootTranslatorTests.cs b/test/coverlet.core.tests/Helpers/SourceRootTranslatorTests.cs index 590f1a233..0768b9a70 100644 --- a/test/coverlet.core.tests/Helpers/SourceRootTranslatorTests.cs +++ b/test/coverlet.core.tests/Helpers/SourceRootTranslatorTests.cs @@ -1,5 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.IO; using Coverlet.Core.Abstractions; using Coverlet.Tests.Xunit.Extensions; using Moq; @@ -15,15 +17,15 @@ public class SourceRootTranslatorTests public void Translate_Success() { string fileToTranslate = "/_/src/coverlet.core/obj/Debug/netstandard2.0/coverlet.core.pdb"; - Mock logger = new Mock(); - Mock fileSystem = new Mock(); + var logger = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string p) => { if (p == "testLib.dll" || p == @"C:\git\coverlet\src\coverlet.core\obj\Debug\netstandard2.0\coverlet.core.pdb" || p == "CoverletSourceRootsMapping") return true; return false; }); fileSystem.Setup(f => f.ReadAllLines(It.IsAny())).Returns(File.ReadAllLines(@"TestAssets/CoverletSourceRootsMappingTest")); - SourceRootTranslator translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); + var translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); Assert.Equal(@"C:\git\coverlet\src\coverlet.core\obj\Debug\netstandard2.0\coverlet.core.pdb", translator.ResolveFilePath(fileToTranslate)); Assert.Equal(@"C:\git\coverlet\src\coverlet.core\obj\Debug\netstandard2.0\coverlet.core.pdb", translator.ResolveFilePath(fileToTranslate)); } @@ -33,15 +35,15 @@ public void Translate_Success() [SkipOnOS(OS.MacOS, "Windows path format only")] public void TranslatePathRoot_Success() { - Mock logger = new Mock(); - Mock fileSystem = new Mock(); + var logger = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string p) => { if (p == "testLib.dll" || p == @"C:\git\coverlet\src\coverlet.core\obj\Debug\netstandard2.0\coverlet.core.pdb" || p == "CoverletSourceRootsMapping") return true; return false; }); fileSystem.Setup(f => f.ReadAllLines(It.IsAny())).Returns(File.ReadAllLines(@"TestAssets/CoverletSourceRootsMappingTest")); - SourceRootTranslator translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); + var translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); Assert.Equal(@"C:\git\coverlet\", translator.ResolvePathRoot("/_/")[0].OriginalPath); } @@ -49,15 +51,15 @@ public void TranslatePathRoot_Success() public void Translate_EmptyFile() { string fileToTranslate = "/_/src/coverlet.core/obj/Debug/netstandard2.0/coverlet.core.pdb"; - Mock logger = new Mock(); - Mock fileSystem = new Mock(); + var logger = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string p) => { if (p == "testLib.dll" || p == "CoverletSourceRootsMapping") return true; return false; }); fileSystem.Setup(f => f.ReadAllLines(It.IsAny())).Returns(new string[0]); - SourceRootTranslator translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); + var translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); Assert.Equal(fileToTranslate, translator.ResolveFilePath(fileToTranslate)); } @@ -65,15 +67,15 @@ public void Translate_EmptyFile() public void Translate_MalformedFile() { string fileToTranslate = "/_/src/coverlet.core/obj/Debug/netstandard2.0/coverlet.core.pdb"; - Mock logger = new Mock(); - Mock fileSystem = new Mock(); + var logger = new Mock(); + var fileSystem = new Mock(); fileSystem.Setup(f => f.Exists(It.IsAny())).Returns((string p) => { if (p == "testLib.dll" || p == "CoverletSourceRootsMapping") return true; return false; }); fileSystem.Setup(f => f.ReadAllLines(It.IsAny())).Returns(new string[1] { "malformedRow" }); - SourceRootTranslator translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); + var translator = new SourceRootTranslator("testLib.dll", logger.Object, fileSystem.Object); Assert.Equal(fileToTranslate, translator.ResolveFilePath(fileToTranslate)); logger.Verify(l => l.LogWarning(It.IsAny()), Times.Once); } diff --git a/test/coverlet.core.tests/Instrumentation/InstrumenterResultTests.cs b/test/coverlet.core.tests/Instrumentation/InstrumenterResultTests.cs index 7e2774a8c..f3ca69aed 100644 --- a/test/coverlet.core.tests/Instrumentation/InstrumenterResultTests.cs +++ b/test/coverlet.core.tests/Instrumentation/InstrumenterResultTests.cs @@ -1,7 +1,7 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. using Xunit; -using Coverlet.Core.Instrumentation; -using System.Collections.Generic; using System.Linq; namespace Coverlet.Core.Instrumentation.Tests @@ -11,14 +11,14 @@ public class InstrumenterResultTests [Fact] public void TestEnsureDocumentsPropertyNotNull() { - InstrumenterResult result = new InstrumenterResult(); + var result = new InstrumenterResult(); Assert.NotNull(result.Documents); } [Fact] public void TestEnsureLinesAndBranchesPropertyNotNull() { - Document document = new Document(); + var document = new Document(); Assert.NotNull(document.Lines); Assert.NotNull(document.Branches); } @@ -26,13 +26,13 @@ public void TestEnsureLinesAndBranchesPropertyNotNull() [Fact] public void CoveragePrepareResult_SerializationRoundTrip() { - CoveragePrepareResult cpr = new CoveragePrepareResult(); + var cpr = new CoveragePrepareResult(); cpr.Identifier = "Identifier"; cpr.MergeWith = "MergeWith"; cpr.ModuleOrDirectory = "Module"; cpr.UseSourceLink = true; - InstrumenterResult ir = new InstrumenterResult(); + var ir = new InstrumenterResult(); ir.HitsFilePath = "HitsFilePath"; ir.Module = "Module"; ir.ModulePath = "ModulePath"; @@ -95,7 +95,7 @@ public void CoveragePrepareResult_SerializationRoundTrip() ir.Documents.Add("key2", doc2); cpr.Results = new InstrumenterResult[] { ir }; - CoveragePrepareResult roundTrip = CoveragePrepareResult.Deserialize(CoveragePrepareResult.Serialize(cpr)); + var roundTrip = CoveragePrepareResult.Deserialize(CoveragePrepareResult.Serialize(cpr)); Assert.Equal(cpr.Identifier, roundTrip.Identifier); Assert.Equal(cpr.MergeWith, roundTrip.MergeWith); @@ -119,8 +119,8 @@ public void CoveragePrepareResult_SerializationRoundTrip() for (int k = 0; k < cpr.Results[i].Documents.Count; k++) { - var documents = cpr.Results[i].Documents.ToArray(); - var documentsRoundTrip = roundTrip.Results[i].Documents.ToArray(); + System.Collections.Generic.KeyValuePair[] documents = cpr.Results[i].Documents.ToArray(); + System.Collections.Generic.KeyValuePair[] documentsRoundTrip = roundTrip.Results[i].Documents.ToArray(); for (int j = 0; j < documents.Length; j++) { Assert.Equal(documents[j].Key, documentsRoundTrip[j].Key); @@ -129,8 +129,8 @@ public void CoveragePrepareResult_SerializationRoundTrip() for (int v = 0; v < documents[j].Value.Lines.Count; v++) { - var lines = documents[j].Value.Lines.ToArray(); - var linesRoundTrip = documentsRoundTrip[j].Value.Lines.ToArray(); + System.Collections.Generic.KeyValuePair[] lines = documents[j].Value.Lines.ToArray(); + System.Collections.Generic.KeyValuePair[] linesRoundTrip = documentsRoundTrip[j].Value.Lines.ToArray(); Assert.Equal(lines[v].Key, linesRoundTrip[v].Key); Assert.Equal(lines[v].Value.Class, lines[v].Value.Class); @@ -141,8 +141,8 @@ public void CoveragePrepareResult_SerializationRoundTrip() for (int v = 0; v < documents[j].Value.Branches.Count; v++) { - var branches = documents[j].Value.Branches.ToArray(); - var branchesRoundTrip = documentsRoundTrip[j].Value.Branches.ToArray(); + System.Collections.Generic.KeyValuePair[] branches = documents[j].Value.Branches.ToArray(); + System.Collections.Generic.KeyValuePair[] branchesRoundTrip = documentsRoundTrip[j].Value.Branches.ToArray(); Assert.Equal(branches[v].Key, branchesRoundTrip[v].Key); Assert.Equal(branches[v].Value.Class, branchesRoundTrip[v].Value.Class); @@ -159,4 +159,4 @@ public void CoveragePrepareResult_SerializationRoundTrip() } } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs b/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs index dcdbc9499..907f5cc66 100644 --- a/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs +++ b/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs @@ -1,10 +1,12 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; - using Coverlet.Core.Helpers; using Coverlet.Core.Abstractions; using Coverlet.Core.Samples.Tests; @@ -29,10 +31,7 @@ public class InstrumenterTests : IDisposable public void Dispose() { - if (disposeAction != null) - { - disposeAction(); - } + disposeAction?.Invoke(); } [ConditionalFact] @@ -47,12 +46,12 @@ public void TestCoreLibInstrumentation() "System.Private.CoreLib.pdb" }; - foreach (var file in files) + foreach (string file in files) { File.Copy(Path.Combine(Directory.GetCurrentDirectory(), "TestAssets", file), Path.Combine(directory.FullName, file), overwrite: true); } - Mock partialMockFileSystem = new Mock(); + var partialMockFileSystem = new Mock(); partialMockFileSystem.CallBase = true; partialMockFileSystem.Setup(fs => fs.OpenRead(It.IsAny())).Returns((string path) => { @@ -84,10 +83,10 @@ public void TestCoreLibInstrumentation() } }); var sourceRootTranslator = new SourceRootTranslator(_mockLogger.Object, new FileSystem()); - CoverageParameters parameters = new CoverageParameters(); - InstrumentationHelper instrumentationHelper = + var parameters = new CoverageParameters(); + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), partialMockFileSystem.Object, _mockLogger.Object, sourceRootTranslator); - Instrumenter instrumenter = new Instrumenter(Path.Combine(directory.FullName, files[0]), "_coverlet_instrumented", parameters, _mockLogger.Object, instrumentationHelper, partialMockFileSystem.Object, sourceRootTranslator, new CecilSymbolHelper()); + var instrumenter = new Instrumenter(Path.Combine(directory.FullName, files[0]), "_coverlet_instrumented", parameters, _mockLogger.Object, instrumentationHelper, partialMockFileSystem.Object, sourceRootTranslator, new CecilSymbolHelper()); Assert.True(instrumenter.CanInstrument()); InstrumenterResult result = instrumenter.Instrument(); @@ -105,9 +104,9 @@ public void TestCoreLibInstrumentation() [InlineData(false)] public void TestInstrument(bool singleHit) { - var instrumenterTest = CreateInstrumentor(singleHit: singleHit); + InstrumenterTest instrumenterTest = CreateInstrumentor(singleHit: singleHit); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); Assert.Equal(Path.GetFileNameWithoutExtension(instrumenterTest.Module), result.Module); Assert.Equal(instrumenterTest.Module, result.ModulePath); @@ -120,9 +119,9 @@ public void TestInstrument(bool singleHit) [InlineData(false)] public void TestInstrumentCoreLib(bool singleHit) { - var instrumenterTest = CreateInstrumentor(fakeCoreLibModule: true, singleHit: singleHit); + InstrumenterTest instrumenterTest = CreateInstrumentor(fakeCoreLibModule: true, singleHit: singleHit); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); Assert.Equal(Path.GetFileNameWithoutExtension(instrumenterTest.Module), result.Module); Assert.Equal(instrumenterTest.Module, result.ModulePath); @@ -135,13 +134,13 @@ public void TestInstrumentCoreLib(bool singleHit) [InlineData(typeof(ClassExcludedByCoverletCodeCoverageAttr))] public void TestInstrument_ClassesWithExcludeAttributeAreExcluded(Type excludedType) { - var instrumenterTest = CreateInstrumentor(); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); - var found = doc.Lines.Values.Any(l => l.Class == excludedType.FullName); + bool found = doc.Lines.Values.Any(l => l.Class == excludedType.FullName); Assert.False(found, "Class decorated with with exclude attribute should be excluded"); instrumenterTest.Directory.Delete(true); @@ -151,13 +150,13 @@ public void TestInstrument_ClassesWithExcludeAttributeAreExcluded(Type excludedT [InlineData(typeof(ClassExcludedByAttrWithoutAttributeNameSuffix), nameof(TestSDKAutoGeneratedCode))] public void TestInstrument_ClassesWithExcludeAttributeWithoutAttributeNameSuffixAreExcluded(Type excludedType, string excludedAttribute) { - var instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); - var found = doc.Lines.Values.Any(l => l.Class == excludedType.FullName); + bool found = doc.Lines.Values.Any(l => l.Class == excludedType.FullName); Assert.False(found, "Class decorated with with exclude attribute should be excluded"); instrumenterTest.Directory.Delete(true); @@ -169,13 +168,13 @@ public void TestInstrument_ClassesWithExcludeAttributeWithoutAttributeNameSuffix [InlineData(nameof(TestSDKAutoGeneratedCode))] public void TestInstrument_ClassesWithCustomExcludeAttributeAreExcluded(string excludedAttribute) { - var instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); #pragma warning disable CS0612 // Type or member is obsolete - var found = doc.Lines.Values.Any(l => l.Class.Equals(nameof(ClassExcludedByObsoleteAttr))); + bool found = doc.Lines.Values.Any(l => l.Class.Equals(nameof(ClassExcludedByObsoleteAttr))); #pragma warning restore CS0612 // Type or member is obsolete Assert.False(found, "Class decorated with with exclude attribute should be excluded"); @@ -188,13 +187,13 @@ public void TestInstrument_ClassesWithCustomExcludeAttributeAreExcluded(string e [InlineData(nameof(TestSDKAutoGeneratedCode), "ClassExcludedByAttrWithoutAttributeNameSuffix")] public void TestInstrument_ClassesWithMethodWithCustomExcludeAttributeAreExcluded(string excludedAttribute, string testClassName) { - var instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); #pragma warning disable CS0612 // Type or member is obsolete - var found = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::Method(System.String)")); + bool found = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::Method(System.String)")); #pragma warning restore CS0612 // Type or member is obsolete Assert.False(found, "Method decorated with with exclude attribute should be excluded"); @@ -207,18 +206,18 @@ public void TestInstrument_ClassesWithMethodWithCustomExcludeAttributeAreExclude [InlineData(nameof(TestSDKAutoGeneratedCode), "ClassExcludedByAttrWithoutAttributeNameSuffix")] public void TestInstrument_ClassesWithPropertyWithCustomExcludeAttributeAreExcluded(string excludedAttribute, string testClassName) { - var instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(attributesToIgnore: new string[] { excludedAttribute }); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); #pragma warning disable CS0612 // Type or member is obsolete - var getFound = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::get_Property()")); + bool getFound = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::get_Property()")); #pragma warning restore CS0612 // Type or member is obsolete Assert.False(getFound, "Property getter decorated with with exclude attribute should be excluded"); #pragma warning disable CS0612 // Type or member is obsolete - var setFound = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::set_Property()")); + bool setFound = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::set_Property()")); #pragma warning restore CS0612 // Type or member is obsolete Assert.False(setFound, "Property setter decorated with with exclude attribute should be excluded"); @@ -248,7 +247,7 @@ private InstrumenterTest CreateInstrumentor(bool fakeCoreLibModule = false, stri File.Copy(module, Path.Combine(directory.FullName, destModule), true); File.Copy(pdb, Path.Combine(directory.FullName, destPdb), true); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(new Mock().Object, new FileSystem())); module = Path.Combine(directory.FullName, destModule); @@ -257,7 +256,7 @@ private InstrumenterTest CreateInstrumentor(bool fakeCoreLibModule = false, stri ExcludeAttributes = attributesToIgnore, DoesNotReturnAttributes = new string[] { "DoesNotReturnAttribute" } }; - Instrumenter instrumenter = new Instrumenter(module, identifier, parameters, _mockLogger.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(_mockLogger.Object, new FileSystem()), new CecilSymbolHelper()); + var instrumenter = new Instrumenter(module, identifier, parameters, _mockLogger.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(_mockLogger.Object, new FileSystem()), new CecilSymbolHelper()); return new InstrumenterTest { Instrumenter = instrumenter, @@ -281,7 +280,7 @@ class InstrumenterTest [Fact] public void TestInstrument_NetStandardAwareAssemblyResolver_FromRuntime() { - NetstandardAwareAssemblyResolver netstandardResolver = new NetstandardAwareAssemblyResolver(null, _mockLogger.Object); + var netstandardResolver = new NetstandardAwareAssemblyResolver(null, _mockLogger.Object); // We ask for "official" netstandard.dll implementation with know MS public key cc7b13ffcd2ddd51 same in all runtime AssemblyDefinition resolved = netstandardResolver.Resolve(AssemblyNameReference.Parse("netstandard, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51")); @@ -298,7 +297,7 @@ public void TestInstrument_NetStandardAwareAssemblyResolver_FromFolder() // conflicts with "official" resolution // We create dummy netstandard.dll - CSharpCompilation compilation = CSharpCompilation.Create( + var compilation = CSharpCompilation.Create( "netstandard", new[] { CSharpSyntaxTree.ParseText("") }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, @@ -315,7 +314,7 @@ public void TestInstrument_NetStandardAwareAssemblyResolver_FromFolder() File.WriteAllBytes("netstandard.dll", dllStream.ToArray()); } - NetstandardAwareAssemblyResolver netstandardResolver = new NetstandardAwareAssemblyResolver(newAssemlby.Location, _mockLogger.Object); + var netstandardResolver = new NetstandardAwareAssemblyResolver(newAssemlby.Location, _mockLogger.Object); AssemblyDefinition resolved = netstandardResolver.Resolve(AssemblyNameReference.Parse(newAssemlby.FullName)); // We check if final netstandard.dll resolved is local folder one and not "official" netstandard.dll @@ -429,11 +428,11 @@ public void SkipEmbeddedPpdbWithoutLocalSource() string xunitDll = Directory.GetFiles(Directory.GetCurrentDirectory(), "xunit.core.dll").First(); var loggerMock = new Mock(); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(xunitDll, new Mock().Object, new FileSystem())); - Instrumenter instrumenter = new Instrumenter(xunitDll, "_xunit_instrumented", new CoverageParameters(), loggerMock.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(xunitDll, loggerMock.Object, new FileSystem()), new CecilSymbolHelper()); + var instrumenter = new Instrumenter(xunitDll, "_xunit_instrumented", new CoverageParameters(), loggerMock.Object, instrumentationHelper, new FileSystem(), new SourceRootTranslator(xunitDll, loggerMock.Object, new FileSystem()), new CecilSymbolHelper()); Assert.True(instrumentationHelper.HasPdb(xunitDll, out bool embedded)); Assert.True(embedded); Assert.False(instrumenter.CanInstrument()); @@ -461,7 +460,7 @@ public void SkipPpdbWithoutLocalSource() string dllFileName = "75d9f96508d74def860a568f426ea4a4.dll"; string pdbFileName = "75d9f96508d74def860a568f426ea4a4.pdb"; - Mock partialMockFileSystem = new Mock(); + var partialMockFileSystem = new Mock(); partialMockFileSystem.CallBase = true; partialMockFileSystem.Setup(fs => fs.OpenRead(It.IsAny())).Returns((string path) => { @@ -486,11 +485,11 @@ public void SkipPpdbWithoutLocalSource() } }); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), partialMockFileSystem.Object, _mockLogger.Object, new SourceRootTranslator(_mockLogger.Object, new FileSystem())); string sample = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "TestAssets"), dllFileName).First(); var loggerMock = new Mock(); - Instrumenter instrumenter = new Instrumenter(sample, "_75d9f96508d74def860a568f426ea4a4_instrumented", new CoverageParameters(), loggerMock.Object, instrumentationHelper, partialMockFileSystem.Object, new SourceRootTranslator(loggerMock.Object, new FileSystem()), new CecilSymbolHelper()); + var instrumenter = new Instrumenter(sample, "_75d9f96508d74def860a568f426ea4a4_instrumented", new CoverageParameters(), loggerMock.Object, instrumentationHelper, partialMockFileSystem.Object, new SourceRootTranslator(loggerMock.Object, new FileSystem()), new CecilSymbolHelper()); Assert.True(instrumentationHelper.HasPdb(sample, out bool embedded)); Assert.False(embedded); @@ -503,7 +502,7 @@ public void TestInstrument_MissingModule() { var loggerMock = new Mock(); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(new Mock().Object, new FileSystem())); @@ -519,7 +518,7 @@ public void CanInstrumentFSharpAssemblyWithAnonymousRecord() var loggerMock = new Mock(); string sample = Directory.GetFiles(Directory.GetCurrentDirectory(), "coverlet.tests.projectsample.fsharp.dll").First(); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(sample, new Mock().Object, new FileSystem())); @@ -542,8 +541,8 @@ public void TestInstrument_AssemblyMarkedAsExcludeFromCodeCoverage(string attrib { string EmitAssemblyToInstrument(string outputFolder) { - var attributeClassSyntaxTree = CSharpSyntaxTree.ParseText("[System.AttributeUsage(System.AttributeTargets.Assembly)]public class " + attributeName + ":System.Attribute{}"); - var instrumentableClassSyntaxTree = CSharpSyntaxTree.ParseText($@" + SyntaxTree attributeClassSyntaxTree = CSharpSyntaxTree.ParseText("[System.AttributeUsage(System.AttributeTargets.Assembly)]public class " + attributeName + ":System.Attribute{}"); + SyntaxTree instrumentableClassSyntaxTree = CSharpSyntaxTree.ParseText($@" [assembly:{attributeName}] namespace coverlet.tests.projectsample.excludedbyattribute{{ public class SampleClass @@ -556,26 +555,26 @@ public int SampleMethod() }} "); - var compilation = CSharpCompilation.Create(attributeName, new List + CSharpCompilation compilation = CSharpCompilation.Create(attributeName, new List { attributeClassSyntaxTree,instrumentableClassSyntaxTree }).AddReferences( MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location)). WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, false)); - var dllPath = Path.Combine(outputFolder, $"{attributeName}.dll"); - var pdbPath = Path.Combine(outputFolder, $"{attributeName}.pdb"); + string dllPath = Path.Combine(outputFolder, $"{attributeName}.dll"); + string pdbPath = Path.Combine(outputFolder, $"{attributeName}.pdb"); - using (var outputStream = File.Create(dllPath)) - using (var pdbStream = File.Create(pdbPath)) + using (FileStream outputStream = File.Create(dllPath)) + using (FileStream pdbStream = File.Create(pdbPath)) { - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var emitOptions = new EmitOptions(pdbFilePath: pdbPath); - var emitResult = compilation.Emit(outputStream, pdbStream, options: isWindows ? emitOptions : emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb)); + EmitResult emitResult = compilation.Emit(outputStream, pdbStream, options: isWindows ? emitOptions : emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb)); if (!emitResult.Success) { - var message = "Failure to dynamically create dll"; - foreach (var diagnostic in emitResult.Diagnostics) + string message = "Failure to dynamically create dll"; + foreach (Diagnostic diagnostic in emitResult.Diagnostics) { message += Environment.NewLine; message += diagnostic.GetMessage(); @@ -590,7 +589,7 @@ public int SampleMethod() Directory.CreateDirectory(tempDirectory); disposeAction = () => Directory.Delete(tempDirectory, true); - Mock partialMockFileSystem = new Mock(); + var partialMockFileSystem = new Mock(); partialMockFileSystem.CallBase = true; partialMockFileSystem.Setup(fs => fs.NewFileStream(It.IsAny(), It.IsAny(), It.IsAny())).Returns((string path, FileMode mode, FileAccess access) => { @@ -600,12 +599,12 @@ public int SampleMethod() string excludedbyattributeDll = EmitAssemblyToInstrument(tempDirectory); - InstrumentationHelper instrumentationHelper = + var instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(new Mock().Object, new FileSystem())); CoverageParameters parametes = new(); parametes.ExcludeAttributes = excludedAttributes; - Instrumenter instrumenter = new Instrumenter(excludedbyattributeDll, "_xunit_excludedbyattribute", parametes, loggerMock.Object, instrumentationHelper, partialMockFileSystem.Object, new SourceRootTranslator(loggerMock.Object, new FileSystem()), new CecilSymbolHelper()); + var instrumenter = new Instrumenter(excludedbyattributeDll, "_xunit_excludedbyattribute", parametes, loggerMock.Object, instrumentationHelper, partialMockFileSystem.Object, new SourceRootTranslator(loggerMock.Object, new FileSystem()), new CecilSymbolHelper()); InstrumenterResult result = instrumenter.Instrument(); if (expectedExcludes) @@ -622,8 +621,8 @@ public int SampleMethod() [Fact] public void TestInstrument_AspNetCoreSharedFrameworkResolver() { - AspNetCoreSharedFrameworkResolver resolver = new AspNetCoreSharedFrameworkResolver(_mockLogger.Object); - CompilationLibrary compilationLibrary = new CompilationLibrary( + var resolver = new AspNetCoreSharedFrameworkResolver(_mockLogger.Object); + var compilationLibrary = new CompilationLibrary( "package", "Microsoft.Extensions.Logging.Abstractions", "2.2.0", @@ -632,7 +631,7 @@ public void TestInstrument_AspNetCoreSharedFrameworkResolver() Enumerable.Empty(), true); - List assemblies = new List(); + var assemblies = new List(); Assert.True(resolver.TryResolveAssemblyPaths(compilationLibrary, assemblies)); Assert.NotEmpty(assemblies); } @@ -640,7 +639,7 @@ public void TestInstrument_AspNetCoreSharedFrameworkResolver() [Fact] public void TestInstrument_NetstandardAwareAssemblyResolver_PreserveCompilationContext() { - NetstandardAwareAssemblyResolver netstandardResolver = new NetstandardAwareAssemblyResolver(Assembly.GetExecutingAssembly().Location, _mockLogger.Object); + var netstandardResolver = new NetstandardAwareAssemblyResolver(Assembly.GetExecutingAssembly().Location, _mockLogger.Object); AssemblyDefinition asm = netstandardResolver.TryWithCustomResolverOnDotNetCore(new AssemblyNameReference("Microsoft.Extensions.Logging.Abstractions", new Version("2.2.0"))); Assert.NotNull(asm); } @@ -648,10 +647,10 @@ public void TestInstrument_NetstandardAwareAssemblyResolver_PreserveCompilationC [Fact] public void TestInstrument_LambdaInsideMethodWithExcludeAttributeAreExcluded() { - var instrumenterTest = CreateInstrumentor(); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); Assert.NotNull(doc); Assert.Contains(doc.Lines.Values, l => l.Method == "System.Int32 Coverlet.Core.Samples.Tests.MethodsWithExcludeFromCodeCoverageAttr::TestLambda(System.String,System.Int32)"); @@ -669,10 +668,10 @@ public void TestInstrument_LambdaInsideMethodWithExcludeAttributeAreExcluded() [Fact] public void TestInstrument_LocalFunctionInsideMethodWithExcludeAttributeAreExcluded() { - var instrumenterTest = CreateInstrumentor(); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); Assert.NotNull(doc); Assert.Contains(doc.Lines.Values, l => l.Method == "System.Int32 Coverlet.Core.Samples.Tests.MethodsWithExcludeFromCodeCoverageAttr::TestLocalFunction(System.String,System.Int32)"); @@ -694,10 +693,10 @@ public void TestInstrument_LocalFunctionInsideMethodWithExcludeAttributeAreExclu [Fact] public void TestInstrument_YieldInsideMethodWithExcludeAttributeAreExcluded() { - var instrumenterTest = CreateInstrumentor(); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); Assert.NotNull(doc); Assert.DoesNotContain(doc.Lines.Values, l => l.Class.StartsWith("Coverlet.Core.Samples.Tests.MethodsWithExcludeFromCodeCoverageAttr/") && @@ -715,10 +714,10 @@ public void TestInstrument_YieldInsideMethodWithExcludeAttributeAreExcluded() [Fact] public void TestInstrument_AsyncAwaitInsideMethodWithExcludeAttributeAreExcluded() { - var instrumenterTest = CreateInstrumentor(); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.ExcludeFromCoverage.cs"); Assert.NotNull(doc); Assert.DoesNotContain(doc.Lines.Values, l => l.Class.StartsWith("Coverlet.Core.Samples.Tests.MethodsWithExcludeFromCodeCoverageAttr/") && @@ -736,7 +735,7 @@ public void TestInstrument_AsyncAwaitInsideMethodWithExcludeAttributeAreExcluded [Fact] public void TestReachabilityHelper() { - var allInstrumentableLines = + int[] allInstrumentableLines = new[] { // Throws @@ -764,7 +763,7 @@ public void TestReachabilityHelper() // FiltersAndFinallies 171, 173, 174, 175, 176, 177, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 192, 193, 194, 195, 196, 197 }; - var notReachableLines = + int[] notReachableLines = new[] { // NoBranches @@ -787,12 +786,12 @@ public void TestReachabilityHelper() 176, 177, 183, 184, 189, 190, 195, 196, 197 }; - var expectedToBeInstrumented = allInstrumentableLines.Except(notReachableLines).ToArray(); + int[] expectedToBeInstrumented = allInstrumentableLines.Except(notReachableLines).ToArray(); - var instrumenterTest = CreateInstrumentor(); - var result = instrumenterTest.Instrumenter.Instrument(); + InstrumenterTest instrumenterTest = CreateInstrumentor(); + InstrumenterResult result = instrumenterTest.Instrumenter.Instrument(); - var doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.DoesNotReturn.cs"); + Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Instrumentation.DoesNotReturn.cs"); // check for instrumented lines doc.AssertNonInstrumentedLines(BuildConfiguration.Debug, notReachableLines); @@ -800,7 +799,5 @@ public void TestReachabilityHelper() instrumenterTest.Directory.Delete(true); } - - } } diff --git a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs index 7ca7d5c4d..c0b8dd282 100644 --- a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs +++ b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.IO; using System.Threading; @@ -38,7 +41,7 @@ public void HitsFileCorrectlyWritten() ModuleTrackerTemplate.HitsArray = new[] { 1, 2, 0, 3 }; ModuleTrackerTemplate.UnloadModule(null, null); - var expectedHitsArray = new[] { 1, 2, 0, 3 }; + int[] expectedHitsArray = new[] { 1, 2, 0, 3 }; Assert.Equal(expectedHitsArray, ReadHitsFile()); return _success; @@ -63,7 +66,7 @@ public void HitsOnMultipleThreadsCorrectlyCounted() { FunctionExecutor.Run(() => { - List threads = new List(); + var threads = new List(); using var ctx = new TrackerContext(); ModuleTrackerTemplate.HitsArray = new[] { 0, 0, 0, 0 }; for (int i = 0; i < ModuleTrackerTemplate.HitsArray.Length; ++i) @@ -79,12 +82,12 @@ public void HitsOnMultipleThreadsCorrectlyCounted() } ModuleTrackerTemplate.UnloadModule(null, null); - var expectedHitsArray = new[] { 4, 3, 2, 1 }; + int[] expectedHitsArray = new[] { 4, 3, 2, 1 }; Assert.Equal(expectedHitsArray, ReadHitsFile()); static void HitIndex(object index) { - var hitIndex = (int)index; + int hitIndex = (int)index; for (int i = 0; i <= hitIndex; ++i) { ModuleTrackerTemplate.RecordHit(i); @@ -107,7 +110,7 @@ public void MultipleSequentialUnloadsHaveCorrectTotalData() ModuleTrackerTemplate.HitsArray = new[] { 0, 1, 2, 3 }; ModuleTrackerTemplate.UnloadModule(null, null); - var expectedHitsArray = new[] { 0, 4, 4, 4 }; + int[] expectedHitsArray = new[] { 0, 4, 4, 4 }; Assert.Equal(expectedHitsArray, ReadHitsFile()); return _success; @@ -137,7 +140,7 @@ public void MutexBlocksMultipleWriters() mutex.ReleaseMutex(); await unloadTask; - var expectedHitsArray = new[] { 0, 4, 4, 4 }; + int[] expectedHitsArray = new[] { 0, 4, 4, 4 }; Assert.Equal(expectedHitsArray, ReadHitsFile()); } @@ -164,7 +167,7 @@ private int[] ReadHitsFile() using (var fs = new FileStream(ModuleTrackerTemplate.HitsFilePath, FileMode.Open)) using (var br = new BinaryReader(fs)) { - var hitsArray = new int[br.ReadInt32()]; + int[] hitsArray = new int[br.ReadInt32()]; for (int i = 0; i < hitsArray.Length; ++i) { hitsArray[i] = br.ReadInt32(); diff --git a/test/coverlet.core.tests/Properties/AssemblyInfo.cs b/test/coverlet.core.tests/Properties/AssemblyInfo.cs index 78d7bf29b..33d7581ec 100644 --- a/test/coverlet.core.tests/Properties/AssemblyInfo.cs +++ b/test/coverlet.core.tests/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; [assembly: AssemblyKeyFile("coverlet.core.tests.snk")] \ No newline at end of file diff --git a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs index f92c922d2..f54174b70 100644 --- a/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/CoberturaReporterTests.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System; using System.Collections.Generic; using System.Globalization; @@ -7,7 +10,6 @@ using System.Text; using System.Threading; using System.Xml.Linq; - using Coverlet.Core.Abstractions; using Moq; using Xunit; @@ -19,27 +21,27 @@ public class CoberturaReporterTests [Fact] public void TestReport() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Identifier = Guid.NewGuid().ToString(); - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 0); - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 23, EndOffset = 24, Path = 0, Ordinal = 1 }); branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 23, EndOffset = 27, Path = 1, Ordinal = 2 }); - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Reporters.Tests.CoberturaReporterTests::TestReport()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Reporters.Tests.CoberturaReporterTests::TestReport()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Reporters.Tests.CoberturaReporterTests", methods); - Documents documents = new Documents(); + var documents = new Documents(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -62,15 +64,15 @@ public void TestReport() // where decimal char is comma. Assert.Equal("1,5", (1.5).ToString()); - CoberturaReporter reporter = new CoberturaReporter(); + var reporter = new CoberturaReporter(); string report = reporter.Report(result, new Mock().Object); Assert.NotEmpty(report); var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); - var matchingRateAttributes = doc.Descendants().Attributes().Where(attr => attr.Name.LocalName.EndsWith("-rate")); - var rateParentNodeNames = matchingRateAttributes.Select(attr => attr.Parent.Name.LocalName); + IEnumerable matchingRateAttributes = doc.Descendants().Attributes().Where(attr => attr.Name.LocalName.EndsWith("-rate")); + IEnumerable rateParentNodeNames = matchingRateAttributes.Select(attr => attr.Parent.Name.LocalName); Assert.Contains("package", rateParentNodeNames); Assert.Contains("class", rateParentNodeNames); Assert.Contains("method", rateParentNodeNames); @@ -82,8 +84,8 @@ public void TestReport() Assert.Equal(0.5, double.Parse(value, CultureInfo.InvariantCulture)); }); - var matchingComplexityAttributes = doc.Descendants().Attributes().Where(attr => attr.Name.LocalName.Equals("complexity")); - var complexityParentNodeNames = matchingComplexityAttributes.Select(attr => attr.Parent.Name.LocalName); + IEnumerable matchingComplexityAttributes = doc.Descendants().Attributes().Where(attr => attr.Name.LocalName.Equals("complexity")); + IEnumerable complexityParentNodeNames = matchingComplexityAttributes.Select(attr => attr.Parent.Name.LocalName); Assert.Contains("package", complexityParentNodeNames); Assert.Contains("class", complexityParentNodeNames); Assert.Contains("method", complexityParentNodeNames); @@ -113,25 +115,25 @@ public void TestEnsureParseMethodStringCorrectly( string expectedMethodName, string expectedSignature) { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Parameters = new CoverageParameters(); result.Identifier = Guid.NewGuid().ToString(); - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 23, EndOffset = 24, Path = 0, Ordinal = 1 }); - Methods methods = new Methods(); + var methods = new Methods(); methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Google.Protobuf.Reflection.MessageDescriptor", methods); - Documents documents = new Documents(); + var documents = new Documents(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { documents.Add(@"C:\doc.cs", classes); @@ -144,7 +146,7 @@ public void TestEnsureParseMethodStringCorrectly( result.Modules = new Modules(); result.Modules.Add("module", documents); - CoberturaReporter reporter = new CoberturaReporter(); + var reporter = new CoberturaReporter(); string report = reporter.Report(result, new Mock().Object); Assert.NotEmpty(report); @@ -161,7 +163,7 @@ public void TestEnsureParseMethodStringCorrectly( [Fact] public void TestReportWithDifferentDirectories() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Parameters = new CoverageParameters(); result.Identifier = Guid.NewGuid().ToString(); @@ -215,16 +217,16 @@ public void TestReportWithDifferentDirectories() result.Modules = new Modules { { "Module", documents } }; - CoberturaReporter reporter = new CoberturaReporter(); + var reporter = new CoberturaReporter(); string report = reporter.Report(result, new Mock().Object); var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); - List basePaths = doc.Element("coverage").Element("sources").Elements().Select(e => e.Value).ToList(); - List relativePaths = doc.Element("coverage").Element("packages").Element("package") + var basePaths = doc.Element("coverage").Element("sources").Elements().Select(e => e.Value).ToList(); + var relativePaths = doc.Element("coverage").Element("packages").Element("package") .Element("classes").Elements().Select(e => e.Attribute("filename").Value).ToList(); - List possiblePaths = new List(); + var possiblePaths = new List(); foreach (string basePath in basePaths) { foreach (string relativePath in relativePaths) @@ -247,9 +249,9 @@ public void TestReportWithDifferentDirectories() [Fact] public void TestReportWithSourcelinkPaths() { - CoverageResult result = new CoverageResult { Parameters = new CoverageParameters() { UseSourceLink = true }, Identifier = Guid.NewGuid().ToString() }; + var result = new CoverageResult { Parameters = new CoverageParameters() { UseSourceLink = true }, Identifier = Guid.NewGuid().ToString() }; - var absolutePath = + string absolutePath = @"https://raw.githubusercontent.com/johndoe/Coverlet/02c09baa8bfdee3b6cdf4be89bd98c8157b0bc08/Demo.cs"; var classes = new Classes { { "Class", new Methods() } }; @@ -257,14 +259,14 @@ public void TestReportWithSourcelinkPaths() result.Modules = new Modules { { "Module", documents } }; - CoberturaReporter reporter = new CoberturaReporter(); + var reporter = new CoberturaReporter(); string report = reporter.Report(result, new Mock().Object); var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); - var fileName = doc.Element("coverage").Element("packages").Element("package").Element("classes").Elements() + string fileName = doc.Element("coverage").Element("packages").Element("package").Element("classes").Elements() .Select(e => e.Attribute("filename").Value).Single(); Assert.Equal(absolutePath, fileName); } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs index 910b891a0..b6215befe 100644 --- a/test/coverlet.core.tests/Reporters/JsonReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/JsonReporterTests.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using Coverlet.Core.Abstractions; using Moq; using System; @@ -10,28 +13,28 @@ public class JsonReporterTests [Fact] public void TestReport() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Identifier = Guid.NewGuid().ToString(); - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 0); - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Reporters.Tests.JsonReporterTests.TestReport()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Reporters.Tests.JsonReporterTests.TestReport()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Reporters.Tests.JsonReporterTests", methods); - Documents documents = new Documents(); + var documents = new Documents(); documents.Add("doc.cs", classes); result.Modules = new Modules(); result.Modules.Add("module", documents); - JsonReporter reporter = new JsonReporter(); + var reporter = new JsonReporter(); Assert.NotEqual("{\n}", reporter.Report(result, new Mock().Object)); Assert.NotEqual(string.Empty, reporter.Report(result, new Mock().Object)); } diff --git a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs index 9df9f33ca..b7462f152 100644 --- a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs @@ -1,7 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using Coverlet.Core.Abstractions; using Moq; using System; -using System.Collections.Generic; using Xunit; namespace Coverlet.Core.Reporters.Tests @@ -11,33 +13,33 @@ public class LcovReporterTests [Fact] public void TestReport() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Parameters = new CoverageParameters(); result.Identifier = Guid.NewGuid().ToString(); - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 0); - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 23, EndOffset = 24, Path = 0, Ordinal = 1 }); branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 23, EndOffset = 27, Path = 1, Ordinal = 2 }); - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Reporters.Tests.LcovReporterTests.TestReport()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Reporters.Tests.LcovReporterTests.TestReport()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Reporters.Tests.LcovReporterTests", methods); - Documents documents = new Documents(); + var documents = new Documents(); documents.Add("doc.cs", classes); result.Modules = new Modules(); result.Modules.Add("module", documents); - LcovReporter reporter = new LcovReporter(); + var reporter = new LcovReporter(); string report = reporter.Report(result, new Mock().Object); Assert.NotEmpty(report); diff --git a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs index 828e4ab42..678ea9ae2 100644 --- a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using Coverlet.Core.Abstractions; using Moq; using System; @@ -14,17 +17,17 @@ public class OpenCoverReporterTests [Fact] public void TestReport() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Parameters = new CoverageParameters(); result.Identifier = Guid.NewGuid().ToString(); result.Modules = new Modules(); result.Modules.Add("Coverlet.Core.Reporters.Tests", CreateFirstDocuments()); - OpenCoverReporter reporter = new OpenCoverReporter(); + var reporter = new OpenCoverReporter(); string report = reporter.Report(result, new Mock().Object); Assert.NotEmpty(report); - XDocument doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); + var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); Assert.Empty(doc.Descendants().Attributes("sequenceCoverage").Where(v => v.Value != "33.33")); Assert.Empty(doc.Descendants().Attributes("branchCoverage").Where(v => v.Value != "25")); Assert.Empty(doc.Descendants().Attributes("nPathComplexity").Where(v => v.Value != "4")); @@ -33,7 +36,7 @@ public void TestReport() [Fact] public void TestFilesHaveUniqueIdsOverMultipleModules() { - CoverageResult result = new CoverageResult(); + var result = new CoverageResult(); result.Parameters = new CoverageParameters(); result.Identifier = Guid.NewGuid().ToString(); @@ -41,8 +44,8 @@ public void TestFilesHaveUniqueIdsOverMultipleModules() result.Modules.Add("Coverlet.Core.Reporters.Tests", CreateFirstDocuments()); result.Modules.Add("Some.Other.Module", CreateSecondDocuments()); - OpenCoverReporter reporter = new OpenCoverReporter(); - var xml = reporter.Report(result, new Mock().Object); + var reporter = new OpenCoverReporter(); + string xml = reporter.Report(result, new Mock().Object); Assert.NotEqual(string.Empty, xml); Assert.Contains(@"", xml); @@ -59,7 +62,7 @@ public void TestLineBranchCoverage() Parameters = new CoverageParameters() }; - var xml = new OpenCoverReporter().Report(result, new Mock().Object); + string xml = new OpenCoverReporter().Report(result, new Mock().Object); // Line 1: Two branches, no coverage (bec = 2, bev = 0) Assert.Contains(@"", xml); @@ -76,27 +79,27 @@ public void TestLineBranchCoverage() private static Documents CreateFirstDocuments() { - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 0); lines.Add(3, 0); - Branches branches = new Branches(); + var branches = new Branches(); branches.Add(new BranchInfo { Line = 1, Hits = 1, Offset = 23, EndOffset = 24, Path = 0, Ordinal = 1 }); branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 23, EndOffset = 27, Path = 1, Ordinal = 2 }); branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 40, EndOffset = 41, Path = 0, Ordinal = 3 }); branches.Add(new BranchInfo { Line = 1, Hits = 0, Offset = 40, EndOffset = 44, Path = 1, Ordinal = 4 }); - Methods methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Reporters.Tests.OpenCoverReporterTests.TestReport()"; + var methods = new Methods(); + string methodString = "System.Void Coverlet.Core.Reporters.Tests.OpenCoverReporterTests.TestReport()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; - Classes classes = new Classes(); + var classes = new Classes(); classes.Add("Coverlet.Core.Reporters.Tests.OpenCoverReporterTests", methods); - Documents documents = new Documents(); + var documents = new Documents(); documents.Add("doc.cs", classes); return documents; @@ -104,16 +107,16 @@ private static Documents CreateFirstDocuments() private static Documents CreateSecondDocuments() { - Lines lines = new Lines(); + var lines = new Lines(); lines.Add(1, 1); lines.Add(2, 0); - Methods methods = new Methods(); - var methodString = "System.Void Some.Other.Module.TestClass.TestMethod()"; + var methods = new Methods(); + string methodString = "System.Void Some.Other.Module.TestClass.TestMethod()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; - Classes classes2 = new Classes(); + var classes2 = new Classes(); classes2.Add("Some.Other.Module.TestClass", methods); var documents = new Documents(); diff --git a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs index e148fa378..1b0f7ce04 100644 --- a/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs +++ b/test/coverlet.core.tests/Reporters/ReporterFactoryTests.cs @@ -1,4 +1,6 @@ -using Coverlet.Core.Reporters; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using Xunit; namespace Coverlet.Core.Reporters.Tests diff --git a/test/coverlet.core.tests/Reporters/Reporters.cs b/test/coverlet.core.tests/Reporters/Reporters.cs index 5c65f0770..f62886407 100644 --- a/test/coverlet.core.tests/Reporters/Reporters.cs +++ b/test/coverlet.core.tests/Reporters/Reporters.cs @@ -1,5 +1,7 @@ -using System.IO; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.IO; using Coverlet.Core.Abstractions; using Coverlet.MSbuild.Tasks; using Moq; @@ -29,10 +31,10 @@ public class Reporters [InlineData("netcoreapp2.2", "file", "cobertura", "file.netcoreapp2.2.cobertura.xml")] public void Msbuild_ReportWriter(string coverletMultiTargetFrameworksCurrentTFM, string coverletOutput, string reportFormat, string expectedFileName) { - Mock fileSystem = new Mock(); - Mock console = new Mock(); + var fileSystem = new Mock(); + var console = new Mock(); - ReportWriter reportWriter = new ReportWriter( + var reportWriter = new ReportWriter( coverletMultiTargetFrameworksCurrentTFM, // mimic code inside CoverageResultTask.cs Path.GetDirectoryName(coverletOutput), @@ -42,7 +44,7 @@ public void Msbuild_ReportWriter(string coverletMultiTargetFrameworksCurrentTFM, console.Object, new CoverageResult() { Modules = new Modules(), Parameters = new CoverageParameters() }, null); - var path = reportWriter.WriteReport(); + string path = reportWriter.WriteReport(); // Path.Combine depends on OS so we can change only win side to avoid duplication Assert.Equal(path.Replace('/', Path.DirectorySeparatorChar), expectedFileName.Replace('/', Path.DirectorySeparatorChar)); } diff --git a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs index 7ff12a0b1..95fb2642f 100644 --- a/test/coverlet.core.tests/Reporters/TeamCityReporter.cs +++ b/test/coverlet.core.tests/Reporters/TeamCityReporter.cs @@ -1,5 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using Coverlet.Core.Abstractions; using Moq; using Xunit; @@ -52,7 +54,7 @@ public TestCreateReporterTests() }; var methods = new Methods(); - var methodString = "System.Void Coverlet.Core.Reporters.Tests.CoberturaReporterTests::TestReport()"; + string methodString = "System.Void Coverlet.Core.Reporters.Tests.CoberturaReporterTests::TestReport()"; methods.Add(methodString, new Method()); methods[methodString].Lines = lines; methods[methodString].Branches = branches; @@ -89,7 +91,7 @@ public void Format_IsNull() public void Report_ReturnsNonNullString() { // Act - var output = _reporter.Report(_result, new Mock().Object); + string output = _reporter.Report(_result, new Mock().Object); // Assert Assert.False(string.IsNullOrWhiteSpace(output), "Output is not null or whitespace"); @@ -99,7 +101,7 @@ public void Report_ReturnsNonNullString() public void Report_ReportsLineCoverage() { // Act - var output = _reporter.Report(_result, new Mock().Object); + string output = _reporter.Report(_result, new Mock().Object); // Assert Assert.Contains("##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='1']", output); @@ -110,7 +112,7 @@ public void Report_ReportsLineCoverage() public void Report_ReportsBranchCoverage() { // Act - var output = _reporter.Report(_result, new Mock().Object); + string output = _reporter.Report(_result, new Mock().Object); // Assert Assert.Contains("##teamcity[buildStatisticValue key='CodeCoverageAbsBCovered' value='1']", output); @@ -121,11 +123,11 @@ public void Report_ReportsBranchCoverage() public void Report_ReportsMethodCoverage() { // Act - var output = _reporter.Report(_result, new Mock().Object); + string output = _reporter.Report(_result, new Mock().Object); // Assert Assert.Contains("##teamcity[buildStatisticValue key='CodeCoverageAbsMCovered' value='1']", output); Assert.Contains("##teamcity[buildStatisticValue key='CodeCoverageAbsMTotal' value='1']", output); } } -} \ No newline at end of file +} diff --git a/test/coverlet.core.tests/Samples/.editorconfig b/test/coverlet.core.tests/Samples/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.core.tests/Samples/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs b/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs index bfd659a61..7ea79155b 100644 --- a/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs +++ b/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs @@ -1,7 +1,9 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Linq; using System.Reflection; - using Xunit; using Coverlet.Core.Samples.Tests; using coverlet.tests.projectsample.netframework; @@ -19,7 +21,7 @@ public class CecilSymbolHelperTests public CecilSymbolHelperTests() { - var location = GetType().Assembly.Location; + string location = GetType().Assembly.Location; _resolver = new DefaultAssemblyResolver(); _resolver.AddSearchDirectory(Path.GetDirectoryName(location)); _parameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = _resolver }; @@ -31,11 +33,11 @@ public CecilSymbolHelperTests() public void GetBranchPoints_OneBranch() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSingleDecision)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSingleDecision)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -53,11 +55,11 @@ public void GetBranchPoints_OneBranch() public void GetBranchPoints_Using_Where_GeneratedBranchesIgnored() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSimpleUsingStatement)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSimpleUsingStatement)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); Assert.Equal(2, points.Count()); } @@ -66,11 +68,11 @@ public void GetBranchPoints_Using_Where_GeneratedBranchesIgnored() public void GetBranchPoints_GeneratedBranches_DueToCachedAnonymousMethodDelegate_Ignored() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSimpleTaskWithLambda)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSimpleTaskWithLambda)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); Assert.Empty(points); } @@ -79,11 +81,11 @@ public void GetBranchPoints_GeneratedBranches_DueToCachedAnonymousMethodDelegate public void GetBranchPoints_TwoBranch() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasTwoDecisions)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasTwoDecisions)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -98,11 +100,11 @@ public void GetBranchPoints_TwoBranch() public void GetBranchPoints_CompleteIf() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasCompleteIf)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasCompleteIf)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -117,11 +119,11 @@ public void GetBranchPoints_CompleteIf() public void GetBranchPoints_Switch() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitch)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitch)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -140,11 +142,11 @@ public void GetBranchPoints_Switch() public void GetBranchPoints_SwitchWithDefault() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitchWithDefault)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitchWithDefault)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -163,11 +165,11 @@ public void GetBranchPoints_SwitchWithDefault() public void GetBranchPoints_SwitchWithBreaks() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitchWithBreaks)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitchWithBreaks)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -186,11 +188,11 @@ public void GetBranchPoints_SwitchWithBreaks() public void GetBranchPoints_SwitchWithMultipleCases() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitchWithMultipleCases)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.HasSwitchWithMultipleCases)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); @@ -215,15 +217,15 @@ public void GetBranchPoints_AssignsNegativeLineNumberToBranchesInMethodsThatHave * in this case for an anonymous class the compiler will dynamically create an Equals 'utility' method. */ // arrange - var type = _module.Types.First(x => x.FullName.Contains("f__AnonymousType")); - var method = type.Methods.First(x => x.FullName.Contains("::Equals")); + TypeDefinition type = _module.Types.First(x => x.FullName.Contains("f__AnonymousType")); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains("::Equals")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.NotNull(points); - foreach (var branchPoint in points) + foreach (BranchPoint branchPoint in points) Assert.Equal(-1, branchPoint.StartLine); } @@ -231,8 +233,8 @@ public void GetBranchPoints_AssignsNegativeLineNumberToBranchesInMethodsThatHave public void GetBranchPoints_UsingWithException_Issue243_IgnoresBranchInFinallyBlock() { // arrange - var type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); - var method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.UsingWithException_Issue243)}")); + TypeDefinition type = _module.Types.First(x => x.FullName == typeof(DeclaredConstructorClass).FullName); + MethodDefinition method = type.Methods.First(x => x.FullName.Contains($"::{nameof(DeclaredConstructorClass.UsingWithException_Issue243)}")); // check that the method is laid out the way we discovered it to be during the defect // @see https://github.com/OpenCover/opencover/issues/243 @@ -243,7 +245,7 @@ public void GetBranchPoints_UsingWithException_Issue243_IgnoresBranchInFinallyBl Assert.True(method.Body.Instructions.First(i => i.OpCode.FlowControl == FlowControl.Cond_Branch).Offset > method.Body.ExceptionHandlers[0].HandlerStart.Offset); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -253,13 +255,13 @@ public void GetBranchPoints_UsingWithException_Issue243_IgnoresBranchInFinallyBl public void GetBranchPoints_IgnoresSwitchIn_GeneratedMoveNext() { // arrange - var nestedName = typeof(Iterator).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(Iterator).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(Iterator).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(Iterator).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -269,13 +271,13 @@ public void GetBranchPoints_IgnoresSwitchIn_GeneratedMoveNext() public void GetBranchPoints_IgnoresBranchesIn_GeneratedMoveNextForSingletonIterator() { // arrange - var nestedName = typeof(SingletonIterator).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(SingletonIterator).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(SingletonIterator).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(SingletonIterator).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -285,13 +287,13 @@ public void GetBranchPoints_IgnoresBranchesIn_GeneratedMoveNextForSingletonItera public void GetBranchPoints_IgnoresBranchesIn_AsyncAwaitStateMachine() { // arrange - var nestedName = typeof(AsyncAwaitStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncAwaitStateMachine).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AsyncAwaitStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncAwaitStateMachine).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -305,13 +307,13 @@ public void GetBranchPoints_IgnoresBranchesIn_AsyncAwaitStateMachineNetFramework _resolver.AddSearchDirectory(Path.GetDirectoryName(location)); _module = ModuleDefinition.ReadModule(location, _parameters); - var nestedName = typeof(AsyncAwaitStateMachineNetFramework).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncAwaitStateMachineNetFramework).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AsyncAwaitStateMachineNetFramework).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncAwaitStateMachineNetFramework).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -321,13 +323,13 @@ public void GetBranchPoints_IgnoresBranchesIn_AsyncAwaitStateMachineNetFramework public void GetBranchPoints_IgnoresBranchesIn_AsyncAwaitValueTaskStateMachine() { // arrange - var nestedName = typeof(AsyncAwaitValueTaskStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncAwaitValueTaskStateMachine).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AsyncAwaitValueTaskStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncAwaitValueTaskStateMachine).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -337,13 +339,13 @@ public void GetBranchPoints_IgnoresBranchesIn_AsyncAwaitValueTaskStateMachine() public void GetBranchPoints_IgnoresMostBranchesIn_AwaitForeachStateMachine() { // arrange - var nestedName = typeof(AwaitForeachStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AwaitForeachStateMachine).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AwaitForeachStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AwaitForeachStateMachine).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert // We do expect there to be a two-way branch (stay in the loop or not?) on @@ -359,13 +361,13 @@ public void GetBranchPoints_IgnoresMostBranchesIn_AwaitForeachStateMachine() public void GetBranchPoints_IgnoresMostBranchesIn_AwaitForeachStateMachine_WithBranchesWithinIt() { // arrange - var nestedName = typeof(AwaitForeachStateMachine_WithBranches).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AwaitForeachStateMachine_WithBranches).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AwaitForeachStateMachine_WithBranches).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AwaitForeachStateMachine_WithBranches).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert // We do expect there to be four branch points (two places where we can branch @@ -386,13 +388,13 @@ public void GetBranchPoints_IgnoresMostBranchesIn_AwaitForeachStateMachine_WithB public void GetBranchPoints_IgnoresExtraBranchesIn_AsyncIteratorStateMachine() { // arrange - var nestedName = typeof(AsyncIteratorStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncIteratorStateMachine).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AsyncIteratorStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AsyncIteratorStateMachine).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert // We do expect the "for" loop to be a branch with two branch points, but that's it. @@ -406,13 +408,13 @@ public void GetBranchPoints_IgnoresExtraBranchesIn_AsyncIteratorStateMachine() public void GetBranchPoints_IgnoreBranchesIn_AwaitUsingStateMachine() { // arrange - var nestedName = typeof(AwaitUsingStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AwaitUsingStateMachine).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(AwaitUsingStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(AwaitUsingStateMachine).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -422,13 +424,13 @@ public void GetBranchPoints_IgnoreBranchesIn_AwaitUsingStateMachine() public void GetBranchPoints_IgnoreBranchesIn_ScopedAwaitUsingStateMachine() { // arrange - var nestedName = typeof(ScopedAwaitUsingStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; - var type = _module.Types.FirstOrDefault(x => x.FullName == typeof(ScopedAwaitUsingStateMachine).FullName); - var nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); - var method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); + string nestedName = typeof(ScopedAwaitUsingStateMachine).GetNestedTypes(BindingFlags.NonPublic).First().Name; + TypeDefinition type = _module.Types.FirstOrDefault(x => x.FullName == typeof(ScopedAwaitUsingStateMachine).FullName); + TypeDefinition nestedType = type.NestedTypes.FirstOrDefault(x => x.FullName.EndsWith(nestedName)); + MethodDefinition method = nestedType.Methods.First(x => x.FullName.EndsWith("::MoveNext()")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); // assert Assert.Empty(points); @@ -438,12 +440,12 @@ public void GetBranchPoints_IgnoreBranchesIn_ScopedAwaitUsingStateMachine() public void GetBranchPoints_ExceptionFilter() { // arrange - var type = _module.Types.Single(x => x.FullName == typeof(ExceptionFilter).FullName); - var method = type.Methods.Single(x => x.FullName.Contains($"::{nameof(ExceptionFilter.Test)}")); + TypeDefinition type = _module.Types.Single(x => x.FullName == typeof(ExceptionFilter).FullName); + MethodDefinition method = type.Methods.Single(x => x.FullName.Contains($"::{nameof(ExceptionFilter.Test)}")); // act - var points = _cecilSymbolHelper.GetBranchPoints(method); + System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); Assert.Empty(points); } } -} \ No newline at end of file +} diff --git a/test/coverlet.integration.determisticbuild/.editorconfig b/test/coverlet.integration.determisticbuild/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.integration.determisticbuild/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.integration.template/.editorconfig b/test/coverlet.integration.template/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.integration.template/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.integration.tests/AssertHelper.cs b/test/coverlet.integration.tests/AssertHelper.cs index 4fa6e0658..a8ab085db 100644 --- a/test/coverlet.integration.tests/AssertHelper.cs +++ b/test/coverlet.integration.tests/AssertHelper.cs @@ -1,8 +1,10 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; - using Coverlet.Core; using Xunit.Sdk; @@ -17,7 +19,6 @@ public static Classes Document(this Modules modules, string docName) throw new ArgumentNullException(nameof(docName)); } - foreach (KeyValuePair module in modules) { foreach (KeyValuePair document in module.Value) @@ -39,7 +40,6 @@ public static Methods Class(this Classes classes, string className) throw new ArgumentNullException(nameof(className)); } - foreach (KeyValuePair @class in classes) { if (@class.Key == className) @@ -58,7 +58,6 @@ public static Method Method(this Methods methods, string methodName) throw new ArgumentNullException(nameof(methodName)); } - foreach (KeyValuePair method in methods) { if (method.Key.Contains(methodName)) @@ -77,7 +76,7 @@ public static void AssertLinesCovered(this Method method, params (int line, int throw new ArgumentNullException(nameof(lines)); } - List linesToCover = new List(lines.Select(l => l.line)); + var linesToCover = new List(lines.Select(l => l.line)); foreach (KeyValuePair line in method.Lines) { diff --git a/test/coverlet.integration.tests/BaseTest.cs b/test/coverlet.integration.tests/BaseTest.cs index be15680dd..6072740c7 100644 --- a/test/coverlet.integration.tests/BaseTest.cs +++ b/test/coverlet.integration.tests/BaseTest.cs @@ -1,11 +1,12 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Diagnostics; using System.IO; using System.Linq; -using System.Reflection; using System.Threading; using System.Xml.Linq; - using Coverlet.Core; using Newtonsoft.Json; using NuGet.Packaging; @@ -46,7 +47,7 @@ private protected string GetPackageVersion(string filter) using Stream pkg = File.OpenRead(Directory.GetFiles($"../../../../../bin/{GetAssemblyBuildConfiguration()}/Packages", filter).Single()); using var reader = new PackageArchiveReader(pkg); using Stream nuspecStream = reader.GetNuspec(); - Manifest manifest = Manifest.ReadFrom(nuspecStream, false); + var manifest = Manifest.ReadFrom(nuspecStream, false); return manifest.Metadata.Version.OriginalVersion; } @@ -81,7 +82,7 @@ private protected ClonedTemplateProject CloneTemplateProject(bool cleanupOnDispo private protected bool RunCommand(string command, string arguments, out string standardOutput, out string standardError, string workingDirectory = "") { Debug.WriteLine($"BaseTest.RunCommand: {command} {arguments}\nWorkingDirectory: {workingDirectory}"); - ProcessStartInfo psi = new ProcessStartInfo(command, arguments); + var psi = new ProcessStartInfo(command, arguments); psi.WorkingDirectory = workingDirectory; psi.RedirectStandardError = true; psi.RedirectStandardOutput = true; @@ -108,7 +109,7 @@ private protected void UpdateNugeConfigtWithLocalPackageFolder(string projectPat throw new FileNotFoundException("Nuget.config not found", "nuget.config"); } XDocument xml; - using (var nugetFileStream = File.OpenRead(nugetFile)) + using (FileStream? nugetFileStream = File.OpenRead(nugetFile)) { xml = XDocument.Load(nugetFileStream); } @@ -130,7 +131,7 @@ private void SetIsTestProjectTrue(string projectPath) throw new FileNotFoundException("coverlet.integration.template.csproj not found", "coverlet.integration.template.csproj"); } XDocument xml; - using (var csprojStream = File.OpenRead(csproj)) + using (FileStream? csprojStream = File.OpenRead(csproj)) { xml = XDocument.Load(csprojStream); } @@ -150,7 +151,7 @@ private protected void AddMicrosoftNETTestSdkRef(string projectPath, string vers throw new FileNotFoundException("coverlet.integration.template.csproj not found", "coverlet.integration.template.csproj"); } XDocument xml; - using (var csprojStream = File.OpenRead(csproj)) + using (FileStream? csprojStream = File.OpenRead(csproj)) { xml = XDocument.Load(csprojStream); } @@ -170,7 +171,7 @@ private protected void AddCoverletMsbuildRef(string projectPath) throw new FileNotFoundException("coverlet.integration.template.csproj not found", "coverlet.integration.template.csproj"); } XDocument xml; - using (var csprojStream = File.OpenRead(csproj)) + using (FileStream? csprojStream = File.OpenRead(csproj)) { xml = XDocument.Load(csprojStream); } @@ -189,7 +190,7 @@ private protected void AddCoverletCollectosRef(string projectPath) throw new FileNotFoundException("coverlet.integration.template.csproj not found", "coverlet.integration.template.csproj"); } XDocument xml; - using (var csprojStream = File.OpenRead(csproj)) + using (FileStream? csprojStream = File.OpenRead(csproj)) { xml = XDocument.Load(csprojStream); } @@ -257,7 +258,7 @@ private protected void UpdateProjectTargetFramework(ClonedTemplateProject projec throw new FileNotFoundException("coverlet.integration.template.csproj not found", "coverlet.integration.template.csproj"); } XDocument xml; - using (var csprojStream = File.OpenRead(project.ProjectFileNamePath)) + using (FileStream? csprojStream = File.OpenRead(project.ProjectFileNamePath)) { xml = XDocument.Load(csprojStream); } @@ -327,15 +328,15 @@ public ClonedTemplateProject(string? projectRootPath, bool cleanupOnDispose) public bool IsMultipleTargetFramework() { - using var csprojStream = File.OpenRead(ProjectFileNamePath); - XDocument xml = XDocument.Load(csprojStream); + using FileStream? csprojStream = File.OpenRead(ProjectFileNamePath); + var xml = XDocument.Load(csprojStream); return xml.Element("Project")!.Element("PropertyGroup")!.Element("TargetFramework") == null; } public string[] GetTargetFrameworks() { - using var csprojStream = File.OpenRead(ProjectFileNamePath); - XDocument xml = XDocument.Load(csprojStream); + using FileStream? csprojStream = File.OpenRead(ProjectFileNamePath); + var xml = XDocument.Load(csprojStream); XElement element = xml.Element("Project")!.Element("PropertyGroup")!.Element("TargetFramework") ?? xml.Element("Project")!.Element("PropertyGroup")!.Element("TargetFrameworks")!; if (element is null) { diff --git a/test/coverlet.integration.tests/Collectors.cs b/test/coverlet.integration.tests/Collectors.cs index 52adb820b..262f29d58 100644 --- a/test/coverlet.integration.tests/Collectors.cs +++ b/test/coverlet.integration.tests/Collectors.cs @@ -1,7 +1,9 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.IO; using System.Linq; - using Xunit; namespace Coverlet.Integration.Tests @@ -42,7 +44,7 @@ public TestSDK_Preview() public abstract class Collectors : BaseTest { - private string _buildConfiguration; + private readonly string _buildConfiguration; public Collectors() { diff --git a/test/coverlet.integration.tests/DeterministicBuild.cs b/test/coverlet.integration.tests/DeterministicBuild.cs index 1013e2303..b9f11a047 100644 --- a/test/coverlet.integration.tests/DeterministicBuild.cs +++ b/test/coverlet.integration.tests/DeterministicBuild.cs @@ -1,8 +1,10 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.IO; using System.Linq; using System.Xml.Linq; - using Coverlet.Core; using Newtonsoft.Json; using Xunit; @@ -23,7 +25,7 @@ public DeterministicBuild() private void CreateDeterministicTestPropsFile() { - XDocument deterministicTestProps = new XDocument(); + var deterministicTestProps = new XDocument(); deterministicTestProps.Add( new XElement("Project", new XElement("PropertyGroup", diff --git a/test/coverlet.integration.tests/DotnetTool.cs b/test/coverlet.integration.tests/DotnetTool.cs index da5d96628..58f2521ac 100644 --- a/test/coverlet.integration.tests/DotnetTool.cs +++ b/test/coverlet.integration.tests/DotnetTool.cs @@ -1,7 +1,9 @@ -using Coverlet.Tests.Xunit.Extensions; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Coverlet.Tests.Xunit.Extensions; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using Xunit; namespace Coverlet.Integration.Tests diff --git a/test/coverlet.integration.tests/Msbuild.cs b/test/coverlet.integration.tests/Msbuild.cs index 856b512b5..b79f356cf 100644 --- a/test/coverlet.integration.tests/Msbuild.cs +++ b/test/coverlet.integration.tests/Msbuild.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.IO; using System.Linq; using Xunit; @@ -6,7 +9,7 @@ namespace Coverlet.Integration.Tests { public class Msbuild : BaseTest { - private string _buildConfiguration; + private readonly string _buildConfiguration; public Msbuild() { diff --git a/test/coverlet.integration.tests/Properties/AssemblyInfo.cs b/test/coverlet.integration.tests/Properties/AssemblyInfo.cs index c01eb0d58..73e98ccb6 100644 --- a/test/coverlet.integration.tests/Properties/AssemblyInfo.cs +++ b/test/coverlet.integration.tests/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; [assembly: AssemblyKeyFile("coverlet.integration.tests.snk")] diff --git a/test/coverlet.tests.projectsample.empty/.editorconfig b/test/coverlet.tests.projectsample.empty/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.tests.projectsample.empty/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.tests.projectsample.excludedbyattribute/.editorconfig b/test/coverlet.tests.projectsample.excludedbyattribute/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.tests.projectsample.excludedbyattribute/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.tests.projectsample.netframework/.editorconfig b/test/coverlet.tests.projectsample.netframework/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.tests.projectsample.netframework/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none diff --git a/test/coverlet.tests.xunit.extensions/ConditionalFact.cs b/test/coverlet.tests.xunit.extensions/ConditionalFact.cs index 02870708a..fbcbc82f6 100644 --- a/test/coverlet.tests.xunit.extensions/ConditionalFact.cs +++ b/test/coverlet.tests.xunit.extensions/ConditionalFact.cs @@ -1,5 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using Xunit; using Xunit.Abstractions; using Xunit.Sdk; @@ -37,4 +39,4 @@ protected override string GetSkipReason(IAttributeInfo factAttribute) return _skipReason ?? base.GetSkipReason(factAttribute); } } -} \ No newline at end of file +} diff --git a/test/coverlet.tests.xunit.extensions/Extensions.cs b/test/coverlet.tests.xunit.extensions/Extensions.cs index 42fb3e8d0..2c3ee4a97 100644 --- a/test/coverlet.tests.xunit.extensions/Extensions.cs +++ b/test/coverlet.tests.xunit.extensions/Extensions.cs @@ -1,5 +1,7 @@ -using System.Linq; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Linq; using Xunit.Abstractions; using Xunit.Sdk; @@ -9,9 +11,9 @@ internal static class TestMethodExtensions { public static string EvaluateSkipConditions(this ITestMethod testMethod) { - var testClass = testMethod.TestClass.Class; - var assembly = testMethod.TestClass.TestCollection.TestAssembly.Assembly; - var conditionAttributes = testMethod.Method + ITypeInfo testClass = testMethod.TestClass.Class; + IAssemblyInfo assembly = testMethod.TestClass.TestCollection.TestAssembly.Assembly; + System.Collections.Generic.IEnumerable conditionAttributes = testMethod.Method .GetCustomAttributes(typeof(ITestCondition)) .Concat(testClass.GetCustomAttributes(typeof(ITestCondition))) .Concat(assembly.GetCustomAttributes(typeof(ITestCondition))) diff --git a/test/coverlet.tests.xunit.extensions/ITestCondition.cs b/test/coverlet.tests.xunit.extensions/ITestCondition.cs index a7b3778c3..874ca7b63 100644 --- a/test/coverlet.tests.xunit.extensions/ITestCondition.cs +++ b/test/coverlet.tests.xunit.extensions/ITestCondition.cs @@ -1,4 +1,7 @@ -namespace Coverlet.Tests.Xunit.Extensions +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Coverlet.Tests.Xunit.Extensions { public interface ITestCondition { diff --git a/test/coverlet.tests.xunit.extensions/Properties/AssemblyInfo.cs b/test/coverlet.tests.xunit.extensions/Properties/AssemblyInfo.cs index b030dc19f..3e03952d4 100644 --- a/test/coverlet.tests.xunit.extensions/Properties/AssemblyInfo.cs +++ b/test/coverlet.tests.xunit.extensions/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + using System.Reflection; [assembly: AssemblyKeyFile("coverlet.tests.xunit.extensions.snk")] diff --git a/test/coverlet.tests.xunit.extensions/SkipOnOS.cs b/test/coverlet.tests.xunit.extensions/SkipOnOS.cs index 329a799e4..9463171fb 100644 --- a/test/coverlet.tests.xunit.extensions/SkipOnOS.cs +++ b/test/coverlet.tests.xunit.extensions/SkipOnOS.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Toni Solarin-Sodara +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Runtime.InteropServices; namespace Coverlet.Tests.Xunit.Extensions diff --git a/test/coverlet.testsubject/.editorconfig b/test/coverlet.testsubject/.editorconfig new file mode 100644 index 000000000..d66ee0772 --- /dev/null +++ b/test/coverlet.testsubject/.editorconfig @@ -0,0 +1,8 @@ +# top-most EditorConfig file +# We don't want to import other EditorConfig files and we want +# to ensure no rules are enabled for these asset source files. +root = true + +[*.cs] +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none From 76ffde362449b8084e93171e0d5fcd7e281953eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sun, 20 Feb 2022 12:15:26 +0100 Subject: [PATCH 02/16] Improves unexpected packages folder state error (#1304) Improves unexpected packages folder state error --- test/coverlet.integration.tests/BaseTest.cs | 26 ++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/test/coverlet.integration.tests/BaseTest.cs b/test/coverlet.integration.tests/BaseTest.cs index 6072740c7..0417b1d35 100644 --- a/test/coverlet.integration.tests/BaseTest.cs +++ b/test/coverlet.integration.tests/BaseTest.cs @@ -39,16 +39,30 @@ protected BuildConfiguration GetAssemblyBuildConfiguration() private protected string GetPackageVersion(string filter) { - if (!Directory.Exists($"../../../../../bin/{GetAssemblyBuildConfiguration()}/Packages")) + string packagesPath = $"../../../../../bin/{GetAssemblyBuildConfiguration()}/Packages"; + + if (!Directory.Exists(packagesPath)) { throw new DirectoryNotFoundException("Package directory not found, run 'dotnet pack' on repository root"); } - using Stream pkg = File.OpenRead(Directory.GetFiles($"../../../../../bin/{GetAssemblyBuildConfiguration()}/Packages", filter).Single()); - using var reader = new PackageArchiveReader(pkg); - using Stream nuspecStream = reader.GetNuspec(); - var manifest = Manifest.ReadFrom(nuspecStream, false); - return manifest.Metadata.Version.OriginalVersion; + var files = Directory.GetFiles(packagesPath, filter).ToList(); + if (files.Count == 0) + { + throw new InvalidOperationException($"Could not find any package using filter '{filter}' in folder '{Path.GetFullPath(packagesPath)}'. Make sure 'dotnet pack' was called."); + } + else if (files.Count > 1) + { + throw new InvalidOperationException($"Found more than one package using filter '{filter}' in folder '{Path.GetFullPath(packagesPath)}'. Make sure 'dotnet pack' was only called once."); + } + else + { + using Stream pkg = File.OpenRead(files[0]); + using var reader = new PackageArchiveReader(pkg); + using Stream nuspecStream = reader.GetNuspec(); + var manifest = Manifest.ReadFrom(nuspecStream, false); + return manifest.Metadata.Version.OriginalVersion; + } } private protected ClonedTemplateProject CloneTemplateProject(bool cleanupOnDispose = true, string testSDKVersion = "16.5.0") From 2bb04f21ec30978335ad00b5d52b473c45181070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Thu, 24 Feb 2022 11:23:41 +0100 Subject: [PATCH 03/16] Increase severity of some rules and fix instances (#1305) Increase severity of some rules and fix instances --- .editorconfig | 24 +- .../CoverletCoverageCollector.cs | 10 +- .../DataCollection/CoverletSettingsParser.cs | 30 +- .../CoverletInProcDataCollector.cs | 2 +- src/coverlet.console/Logging/ConsoleLogger.cs | 5 +- src/coverlet.core/Coverage.cs | 2 +- .../Helpers/InstrumentationHelper.cs | 56 ++-- .../Helpers/SourceRootTranslator.cs | 2 +- .../Instrumentation/CecilAssemblyResolver.cs | 52 ++-- .../Instrumentation/Instrumenter.cs | 276 +++++++++--------- .../Instrumentation/ModuleTrackerTemplate.cs | 138 +++++---- .../Instrumentation/ReachabilityHelper.cs | 38 +-- .../Reporters/CoberturaReporter.cs | 7 +- .../Reporters/TeamCityReporter.cs | 8 +- .../Symbols/CecilSymbolHelper.cs | 16 +- .../CoverageResultTask.cs | 4 +- .../InstrumentationTask.cs | 10 +- .../CoverletSettingsParserTests.cs | 4 +- .../Coverage/CoverageTests.cs | 2 +- .../Coverage/InstrumenterHelper.cs | 12 +- .../Helpers/InstrumentationHelperTests.cs | 2 +- .../Instrumentation/InstrumenterTests.cs | 14 +- .../ModuleTrackerTemplateTests.cs | 42 ++- .../Symbols/CecilSymbolHelperTests.cs | 22 +- test/coverlet.integration.tests/BaseTest.cs | 4 +- 25 files changed, 380 insertions(+), 402 deletions(-) diff --git a/.editorconfig b/.editorconfig index 26d6da3ab..1227fcc9b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -87,20 +87,34 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_auto_properties = true:warning dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent +# CA1805: Do not initialize unnecessarily +dotnet_diagnostic.CA1805.severity = warning +# IDE0063: Use simple 'using' statement +dotnet_diagnostic.IDE0063.severity = warning +# IDE0057: Use range operator +dotnet_diagnostic.IDE0057.severity = warning +# IDE0075: Simplify conditional expression +dotnet_diagnostic.IDE0075.severity = warning +# IDE0071: Simplify interpolation +dotnet_diagnostic.IDE0071.severity = warning +# CA1829: Use Length/Count property instead of Count() when available +dotnet_diagnostic.CA1829.severity = warning +# CA1827: Do not use Count() or LongCount() when Any() can be used +dotnet_diagnostic.CA1827.severity = warning ############################### # Naming Conventions # ############################### # Name all constant fields using PascalCase dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style dotnet_naming_symbols.constant_fields.applicable_kinds = field dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_style.pascal_case_style.capitalization = pascal_case # Static fields should have s_ prefix dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields -dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style dotnet_naming_symbols.static_fields.applicable_kinds = field dotnet_naming_symbols.static_fields.required_modifiers = static dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected @@ -109,11 +123,15 @@ dotnet_naming_style.static_prefix_style.capitalization = camel_case # Internal and private fields should be _camelCase dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields -dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style dotnet_naming_symbols.private_internal_fields.applicable_kinds = field dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal dotnet_naming_style.camel_case_underscore_style.required_prefix = _ dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = warning +# IDE0090: Use 'new(...)' +dotnet_diagnostic.IDE0090.severity = warning ############################### # C# Coding Conventions # ############################### diff --git a/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs b/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs index cccbd3d10..e1b27a219 100644 --- a/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs +++ b/src/coverlet.collector/DataCollection/CoverletCoverageCollector.cs @@ -163,15 +163,13 @@ private void OnSessionEnd(object sender, SessionEndEventArgs e) // Get coverage reports IEnumerable<(string report, string fileName)> coverageReports = _coverageManager?.GetCoverageReports(); - if (coverageReports != null && coverageReports.Count() > 0) + if (coverageReports != null && coverageReports.Any()) { // Send result attachments to test platform. - using (var attachmentManager = new AttachmentManager(_dataSink, _dataCollectionContext, _logger, _eqtTrace, _countDownEventFactory.Create(coverageReports.Count(), TimeSpan.FromSeconds(30)))) + using var attachmentManager = new AttachmentManager(_dataSink, _dataCollectionContext, _logger, _eqtTrace, _countDownEventFactory.Create(coverageReports.Count(), TimeSpan.FromSeconds(30))); + foreach ((string report, string fileName) in coverageReports) { - foreach ((string report, string fileName) in coverageReports) - { - attachmentManager.SendCoverageReport(report, fileName); - } + attachmentManager.SendCoverageReport(report, fileName); } } else diff --git a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs index d18d1553d..4440b24d8 100644 --- a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs +++ b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs @@ -66,7 +66,7 @@ public CoverletSettings Parse(XmlElement configurationElement, IEnumerable /// Test modules /// Test module - private string ParseTestModule(IEnumerable testModules) + private static string ParseTestModule(IEnumerable testModules) { // Validate if at least one source present. if (testModules == null || !testModules.Any()) @@ -86,7 +86,7 @@ private string ParseTestModule(IEnumerable testModules) /// /// Configuration element /// Report formats - private string[] ParseReportFormats(XmlElement configurationElement) + private static string[] ParseReportFormats(XmlElement configurationElement) { string[] formats = Array.Empty(); if (configurationElement != null) @@ -103,7 +103,7 @@ private string[] ParseReportFormats(XmlElement configurationElement) /// /// Configuration element /// Filters to include - private string[] ParseIncludeFilters(XmlElement configurationElement) + private static string[] ParseIncludeFilters(XmlElement configurationElement) { XmlElement includeFiltersElement = configurationElement[CoverletConstants.IncludeFiltersElementName]; return SplitElement(includeFiltersElement); @@ -114,7 +114,7 @@ private string[] ParseIncludeFilters(XmlElement configurationElement) /// /// Configuration element /// Directories to include - private string[] ParseIncludeDirectories(XmlElement configurationElement) + private static string[] ParseIncludeDirectories(XmlElement configurationElement) { XmlElement includeDirectoriesElement = configurationElement[CoverletConstants.IncludeDirectoriesElementName]; return SplitElement(includeDirectoriesElement); @@ -125,7 +125,7 @@ private string[] ParseIncludeDirectories(XmlElement configurationElement) /// /// Configuration element /// Filters to exclude - private string[] ParseExcludeFilters(XmlElement configurationElement) + private static string[] ParseExcludeFilters(XmlElement configurationElement) { var excludeFilters = new List { CoverletConstants.DefaultExcludeFilter }; @@ -147,7 +147,7 @@ private string[] ParseExcludeFilters(XmlElement configurationElement) /// /// Configuration element /// Source files to exclude - private string[] ParseExcludeSourceFiles(XmlElement configurationElement) + private static string[] ParseExcludeSourceFiles(XmlElement configurationElement) { XmlElement excludeSourceFilesElement = configurationElement[CoverletConstants.ExcludeSourceFilesElementName]; return SplitElement(excludeSourceFilesElement); @@ -158,7 +158,7 @@ private string[] ParseExcludeSourceFiles(XmlElement configurationElement) /// /// Configuration element /// Attributes to exclude - private string[] ParseExcludeAttributes(XmlElement configurationElement) + private static string[] ParseExcludeAttributes(XmlElement configurationElement) { XmlElement excludeAttributesElement = configurationElement[CoverletConstants.ExcludeAttributesElementName]; return SplitElement(excludeAttributesElement); @@ -169,7 +169,7 @@ private string[] ParseExcludeAttributes(XmlElement configurationElement) /// /// Configuration element /// Merge with attribute - private string ParseMergeWith(XmlElement configurationElement) + private static string ParseMergeWith(XmlElement configurationElement) { XmlElement mergeWithElement = configurationElement[CoverletConstants.MergeWithElementName]; return mergeWithElement?.InnerText; @@ -180,7 +180,7 @@ private string ParseMergeWith(XmlElement configurationElement) /// /// Configuration element /// Use source link flag - private bool ParseUseSourceLink(XmlElement configurationElement) + private static bool ParseUseSourceLink(XmlElement configurationElement) { XmlElement useSourceLinkElement = configurationElement[CoverletConstants.UseSourceLinkElementName]; bool.TryParse(useSourceLinkElement?.InnerText, out bool useSourceLink); @@ -192,7 +192,7 @@ private bool ParseUseSourceLink(XmlElement configurationElement) /// /// Configuration element /// Single hit flag - private bool ParseSingleHit(XmlElement configurationElement) + private static bool ParseSingleHit(XmlElement configurationElement) { XmlElement singleHitElement = configurationElement[CoverletConstants.SingleHitElementName]; bool.TryParse(singleHitElement?.InnerText, out bool singleHit); @@ -204,7 +204,7 @@ private bool ParseSingleHit(XmlElement configurationElement) /// /// Configuration element /// ParseDeterministicReport flag - private bool ParseDeterministicReport(XmlElement configurationElement) + private static bool ParseDeterministicReport(XmlElement configurationElement) { XmlElement deterministicReportElement = configurationElement[CoverletConstants.DeterministicReport]; bool.TryParse(deterministicReportElement?.InnerText, out bool deterministicReport); @@ -216,7 +216,7 @@ private bool ParseDeterministicReport(XmlElement configurationElement) /// /// Configuration element /// Include Test Assembly Flag - private bool ParseIncludeTestAssembly(XmlElement configurationElement) + private static bool ParseIncludeTestAssembly(XmlElement configurationElement) { XmlElement includeTestAssemblyElement = configurationElement[CoverletConstants.IncludeTestAssemblyElementName]; bool.TryParse(includeTestAssemblyElement?.InnerText, out bool includeTestAssembly); @@ -228,7 +228,7 @@ private bool ParseIncludeTestAssembly(XmlElement configurationElement) /// /// Configuration element /// Include Test Assembly Flag - private bool ParseSkipAutoProps(XmlElement configurationElement) + private static bool ParseSkipAutoProps(XmlElement configurationElement) { XmlElement skipAutoPropsElement = configurationElement[CoverletConstants.SkipAutoProps]; bool.TryParse(skipAutoPropsElement?.InnerText, out bool skipAutoProps); @@ -240,7 +240,7 @@ private bool ParseSkipAutoProps(XmlElement configurationElement) /// /// Configuration element /// DoesNotReturn attributes - private string[] ParseDoesNotReturnAttributes(XmlElement configurationElement) + private static string[] ParseDoesNotReturnAttributes(XmlElement configurationElement) { XmlElement doesNotReturnAttributesElement = configurationElement[CoverletConstants.DoesNotReturnAttributesElementName]; return SplitElement(doesNotReturnAttributesElement); @@ -251,7 +251,7 @@ private string[] ParseDoesNotReturnAttributes(XmlElement configurationElement) /// /// The element to split /// An array of the values in the element - private string[] SplitElement(XmlElement element) + private static string[] SplitElement(XmlElement element) { return element?.InnerText?.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Where(value => !string.IsNullOrWhiteSpace(value)).Select(value => value.Trim()).ToArray(); } diff --git a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs index 0ab4066a0..f682b2687 100644 --- a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs +++ b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs @@ -17,7 +17,7 @@ namespace Coverlet.Collector.DataCollection public class CoverletInProcDataCollector : InProcDataCollection { private TestPlatformEqtTrace _eqtTrace; - private bool _enableExceptionLog = false; + private bool _enableExceptionLog; private void AttachDebugger() { diff --git a/src/coverlet.console/Logging/ConsoleLogger.cs b/src/coverlet.console/Logging/ConsoleLogger.cs index 1752ddc43..1e41af504 100644 --- a/src/coverlet.console/Logging/ConsoleLogger.cs +++ b/src/coverlet.console/Logging/ConsoleLogger.cs @@ -9,7 +9,8 @@ namespace Coverlet.Console.Logging { class ConsoleLogger : ILogger { - private static readonly object _sync = new object(); + private static readonly object s_sync = new(); + public LogLevel Level { get; set; } = LogLevel.Normal; public void LogError(string message) => Log(LogLevel.Quiet, message, ConsoleColor.Red); @@ -26,7 +27,7 @@ private void Log(LogLevel level, string message, ConsoleColor color) { if (level < Level) return; - lock (_sync) + lock (s_sync) { ConsoleColor currentForegroundColor; if (color != (currentForegroundColor = ForegroundColor)) diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs index ecd9a834d..b53cdf5d8 100644 --- a/src/coverlet.core/Coverage.cs +++ b/src/coverlet.core/Coverage.cs @@ -330,7 +330,7 @@ private bool BranchInCompilerGeneratedClass(string methodName) return false; } - private Method GetMethodWithSameLineInSameDocument(Classes documentClasses, string compilerGeneratedClassName, int branchLine) + private static Method GetMethodWithSameLineInSameDocument(Classes documentClasses, string compilerGeneratedClassName, int branchLine) { foreach (KeyValuePair @class in documentClasses) { diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index d546ecc27..70dd7b677 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -18,7 +18,7 @@ namespace Coverlet.Core.Helpers internal class InstrumentationHelper : IInstrumentationHelper { private const int RetryAttempts = 12; - private readonly ConcurrentDictionary _backupList = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _backupList = new(); private readonly IRetryHelper _retryHelper; private readonly IFileSystem _fileSystem; private readonly ISourceRootTranslator _sourceRootTranslator; @@ -83,27 +83,25 @@ public string[] GetCoverableModules(string moduleOrAppDirectory, string[] direct public bool HasPdb(string module, out bool embedded) { embedded = false; - using (Stream moduleStream = _fileSystem.OpenRead(module)) - using (var peReader = new PEReader(moduleStream)) + using Stream moduleStream = _fileSystem.OpenRead(module); + using var peReader = new PEReader(moduleStream); + foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { - foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) + if (entry.Type == DebugDirectoryEntryType.CodeView) { - if (entry.Type == DebugDirectoryEntryType.CodeView) + CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); + if (_sourceRootTranslator.ResolveFilePath(codeViewData.Path) == $"{Path.GetFileNameWithoutExtension(module)}.pdb") { - CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); - if (_sourceRootTranslator.ResolveFilePath(codeViewData.Path) == $"{Path.GetFileNameWithoutExtension(module)}.pdb") - { - // PDB is embedded - embedded = true; - return true; - } - - return _fileSystem.Exists(_sourceRootTranslator.ResolveFilePath(codeViewData.Path)); + // PDB is embedded + embedded = true; + return true; } - } - return false; + return _fileSystem.Exists(_sourceRootTranslator.ResolveFilePath(codeViewData.Path)); + } } + + return false; } public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNotFoundDocument) @@ -116,17 +114,15 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot { if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb) { - using (MetadataReaderProvider embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entry)) - { - MetadataReader metadataReader = embeddedMetadataProvider.GetMetadataReader(); + using MetadataReaderProvider embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entry); + MetadataReader metadataReader = embeddedMetadataProvider.GetMetadataReader(); - (bool allDocumentsMatch, string notFoundDocument) = MatchDocumentsWithSources(metadataReader); + (bool allDocumentsMatch, string notFoundDocument) = MatchDocumentsWithSources(metadataReader); - if (!allDocumentsMatch) - { - firstNotFoundDocument = notFoundDocument; - return false; - } + if (!allDocumentsMatch) + { + firstNotFoundDocument = notFoundDocument; + return false; } } } @@ -388,7 +384,7 @@ public void SetLogger(ILogger logger) _logger = logger; } - private bool IsTypeFilterMatch(string module, string type, string[] filters) + private static bool IsTypeFilterMatch(string module, string type, string[] filters) { Debug.Assert(module != null); Debug.Assert(filters != null); @@ -408,7 +404,7 @@ private bool IsTypeFilterMatch(string module, string type, string[] filters) return false; } - private string GetBackupPath(string module, string identifier) + private static string GetBackupPath(string module, string identifier) { return Path.Combine( Path.GetTempPath(), @@ -428,14 +424,14 @@ TimeSpan retryStrategy() return retryStrategy; } - private string WildcardToRegex(string pattern) + private static string WildcardToRegex(string pattern) { return "^" + Regex.Escape(pattern). Replace("\\*", ".*"). Replace("\\?", "?") + "$"; } - private bool IsAssembly(string filePath) + private static bool IsAssembly(string filePath) { Debug.Assert(filePath != null); @@ -453,7 +449,7 @@ private bool IsAssembly(string filePath) } } - private bool IsUnknownModuleInFSharpAssembly(Guid languageGuid, string docName) + private static bool IsUnknownModuleInFSharpAssembly(Guid languageGuid, string docName) { // https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md#document-table-0x30 return languageGuid.Equals(new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3")) diff --git a/src/coverlet.core/Helpers/SourceRootTranslator.cs b/src/coverlet.core/Helpers/SourceRootTranslator.cs index f03c83ff5..4d50fbf81 100644 --- a/src/coverlet.core/Helpers/SourceRootTranslator.cs +++ b/src/coverlet.core/Helpers/SourceRootTranslator.cs @@ -48,7 +48,7 @@ public SourceRootTranslator(string moduleTestPath, ILogger logger, IFileSystem f _sourceToDeterministicPathMapping = LoadSourceToDeterministicPathMapping(_sourceRootMapping); } - private Dictionary> LoadSourceToDeterministicPathMapping(Dictionary> sourceRootMapping) + private static Dictionary> LoadSourceToDeterministicPathMapping(Dictionary> sourceRootMapping) { if (sourceRootMapping is null) { diff --git a/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs b/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs index 0f89edf5f..6a781485d 100644 --- a/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs +++ b/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs @@ -17,21 +17,21 @@ namespace Coverlet.Core.Instrumentation /// In case of testing different runtime i.e. netfx we could find netstandard.dll in folder. /// netstandard.dll is a forward only lib, there is no IL but only forwards to "runtime" implementation. /// For some classes implementation are in different assembly for different runtime for instance: - /// + /// /// For NetFx 4.7 /// // Token: 0x2700072C RID: 1836 /// .class extern forwarder System.Security.Cryptography.X509Certificates.StoreName /// { /// .assembly extern System - /// } - /// + /// } + /// /// For netcoreapp2.2 /// Token: 0x2700072C RID: 1836 /// .class extern forwarder System.Security.Cryptography.X509Certificates.StoreName /// { /// .assembly extern System.Security.Cryptography.X509Certificates /// } - /// + /// /// There is a concrete possibility that Cecil cannot find implementation and throws StackOverflow exception https://github.com/jbevain/cecil/issues/575 /// This custom resolver check if requested lib is a "official" netstandard.dll and load once of "current runtime" with /// correct forwards. @@ -39,10 +39,10 @@ namespace Coverlet.Core.Instrumentation /// internal class NetstandardAwareAssemblyResolver : DefaultAssemblyResolver { - private static readonly System.Reflection.Assembly _netStandardAssembly; - private static readonly string _name; - private static readonly byte[] _publicKeyToken; - private static readonly AssemblyDefinition _assemblyDefinition; + private static readonly System.Reflection.Assembly s_netStandardAssembly; + private static readonly string s_name; + private static readonly byte[] s_publicKeyToken; + private static readonly AssemblyDefinition s_assemblyDefinition; private readonly string _modulePath; private readonly Lazy _compositeResolver; @@ -53,11 +53,11 @@ static NetstandardAwareAssemblyResolver() try { // To be sure to load information of "real" runtime netstandard implementation - _netStandardAssembly = System.Reflection.Assembly.LoadFile(Path.Combine(Path.GetDirectoryName(typeof(object).Assembly.Location), "netstandard.dll")); - System.Reflection.AssemblyName name = _netStandardAssembly.GetName(); - _name = name.Name; - _publicKeyToken = name.GetPublicKeyToken(); - _assemblyDefinition = AssemblyDefinition.ReadAssembly(_netStandardAssembly.Location); + s_netStandardAssembly = System.Reflection.Assembly.LoadFile(Path.Combine(Path.GetDirectoryName(typeof(object).Assembly.Location), "netstandard.dll")); + System.Reflection.AssemblyName name = s_netStandardAssembly.GetName(); + s_name = name.Name; + s_publicKeyToken = name.GetPublicKeyToken(); + s_assemblyDefinition = AssemblyDefinition.ReadAssembly(s_netStandardAssembly.Location); } catch (FileNotFoundException) { @@ -70,7 +70,7 @@ public NetstandardAwareAssemblyResolver(string modulePath, ILogger logger) _modulePath = modulePath; _logger = logger; - // this is lazy because we cannot create AspNetCoreSharedFrameworkResolver if not on .NET Core runtime, + // this is lazy because we cannot create AspNetCoreSharedFrameworkResolver if not on .NET Core runtime, // runtime folders are different _compositeResolver = new Lazy(() => new CompositeCompilationAssemblyResolver(new ICompilationAssemblyResolver[] { @@ -82,26 +82,26 @@ public NetstandardAwareAssemblyResolver(string modulePath, ILogger logger) } // Check name and public key but not version that could be different - private bool CheckIfSearchingNetstandard(AssemblyNameReference name) + private static bool CheckIfSearchingNetstandard(AssemblyNameReference name) { - if (_netStandardAssembly is null) + if (s_netStandardAssembly is null) { return false; } - if (_name != name.Name) + if (s_name != name.Name) { return false; } - if (name.PublicKeyToken.Length != _publicKeyToken.Length) + if (name.PublicKeyToken.Length != s_publicKeyToken.Length) { return false; } for (int i = 0; i < name.PublicKeyToken.Length; i++) { - if (_publicKeyToken[i] != name.PublicKeyToken[i]) + if (s_publicKeyToken[i] != name.PublicKeyToken[i]) { return false; } @@ -114,7 +114,7 @@ public override AssemblyDefinition Resolve(AssemblyNameReference name) { if (CheckIfSearchingNetstandard(name)) { - return _assemblyDefinition; + return s_assemblyDefinition; } else { @@ -136,21 +136,21 @@ public override AssemblyDefinition Resolve(AssemblyNameReference name) } } - private bool IsDotNetCore() + private static bool IsDotNetCore() { // object for .NET Framework is inside mscorlib.dll return Path.GetFileName(typeof(object).Assembly.Location) == "System.Private.CoreLib.dll"; } /// - /// + /// /// We try to manually load assembly. /// To work test project needs to use /// /// /// true /// - /// + /// /// Runtime configuration file doc https://github.com/dotnet/cli/blob/master/Documentation/specs/runtime-configuration-file.md /// /// @@ -202,7 +202,7 @@ internal AssemblyDefinition TryWithCustomResolverOnDotNetCore(AssemblyNameRefere catch (Exception ex) { // if we don't find a lib go on - _logger.LogVerbose($"TryWithCustomResolverOnDotNetCore exception: {ex.ToString()}"); + _logger.LogVerbose($"TryWithCustomResolverOnDotNetCore exception: {ex}"); } } } @@ -218,8 +218,8 @@ internal AssemblyDefinition TryWithCustomResolverOnDotNetCore(AssemblyNameRefere internal class AspNetCoreSharedFrameworkResolver : ICompilationAssemblyResolver { - private readonly string[] _aspNetSharedFrameworkDirs = null; - private readonly ILogger _logger = null; + private readonly string[] _aspNetSharedFrameworkDirs; + private readonly ILogger _logger; public AspNetCoreSharedFrameworkResolver(ILogger logger) { diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 9b2ca6fc7..51b18c07c 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -49,7 +49,7 @@ internal class Instrumenter private readonly string[] _doesNotReturnAttributes; private ReachabilityHelper _reachabilityHelper; - public bool SkipModule { get; set; } = false; + public bool SkipModule { get; set; } public Instrumenter( string module, @@ -185,158 +185,150 @@ private bool Is_System_Threading_Interlocked_CoreLib_Type(TypeDefinition type) // locking issues if we do it while writing. private void CreateReachabilityHelper() { - using (Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.Read)) - using (var resolver = new NetstandardAwareAssemblyResolver(_module, _logger)) + using Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.Read); + using var resolver = new NetstandardAwareAssemblyResolver(_module, _logger); + resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); + var parameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; + if (_isCoreLibrary) { - resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); - var parameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; - if (_isCoreLibrary) - { - parameters.MetadataImporterProvider = new CoreLibMetadataImporterProvider(); - } - - using (var module = ModuleDefinition.ReadModule(stream, parameters)) - { - _reachabilityHelper = ReachabilityHelper.CreateForModule(module, _doesNotReturnAttributes, _logger); - } + parameters.MetadataImporterProvider = new CoreLibMetadataImporterProvider(); } + + using var module = ModuleDefinition.ReadModule(stream, parameters); + _reachabilityHelper = ReachabilityHelper.CreateForModule(module, _doesNotReturnAttributes, _logger); } private void InstrumentModule() { CreateReachabilityHelper(); - using (Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite)) - using (var resolver = new NetstandardAwareAssemblyResolver(_module, _logger)) + using Stream stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite); + using var resolver = new NetstandardAwareAssemblyResolver(_module, _logger); + resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); + var parameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; + if (_isCoreLibrary) { - resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); - var parameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; - if (_isCoreLibrary) + parameters.MetadataImporterProvider = new CoreLibMetadataImporterProvider(); + } + + using var module = ModuleDefinition.ReadModule(stream, parameters); + foreach (CustomAttribute customAttribute in module.Assembly.CustomAttributes) + { + if (IsExcludeAttribute(customAttribute)) { - parameters.MetadataImporterProvider = new CoreLibMetadataImporterProvider(); + _logger.LogVerbose($"Excluded module: '{module}' for assembly level attribute {customAttribute.AttributeType.FullName}"); + SkipModule = true; + return; } + } - using (var module = ModuleDefinition.ReadModule(stream, parameters)) - { - foreach (CustomAttribute customAttribute in module.Assembly.CustomAttributes) - { - if (IsExcludeAttribute(customAttribute)) - { - _logger.LogVerbose($"Excluded module: '{module}' for assembly level attribute {customAttribute.AttributeType.FullName}"); - SkipModule = true; - return; - } - } + bool containsAppContext = module.GetType(nameof(System), nameof(AppContext)) != null; + IEnumerable types = module.GetTypes(); + AddCustomModuleTrackerToModule(module); - bool containsAppContext = module.GetType(nameof(System), nameof(AppContext)) != null; - IEnumerable types = module.GetTypes(); - AddCustomModuleTrackerToModule(module); + CustomDebugInformation sourceLinkDebugInfo = module.CustomDebugInformations.FirstOrDefault(c => c.Kind == CustomDebugInformationKind.SourceLink); + if (sourceLinkDebugInfo != null) + { + _result.SourceLink = ((SourceLinkDebugInformation)sourceLinkDebugInfo).Content; + } - CustomDebugInformation sourceLinkDebugInfo = module.CustomDebugInformations.FirstOrDefault(c => c.Kind == CustomDebugInformationKind.SourceLink); - if (sourceLinkDebugInfo != null) + foreach (TypeDefinition type in types) + { + if ( + !Is_System_Threading_Interlocked_CoreLib_Type(type) && + !IsTypeExcluded(type) && + _instrumentationHelper.IsTypeIncluded(_module, type.FullName, _parameters.IncludeFilters) + ) + { + if (IsSynthesizedMemberToBeExcluded(type)) { - _result.SourceLink = ((SourceLinkDebugInformation)sourceLinkDebugInfo).Content; + (_excludedCompilerGeneratedTypes ??= new List()).Add(type.FullName); } - - foreach (TypeDefinition type in types) + else { - if ( - !Is_System_Threading_Interlocked_CoreLib_Type(type) && - !IsTypeExcluded(type) && - _instrumentationHelper.IsTypeIncluded(_module, type.FullName, _parameters.IncludeFilters) - ) - { - if (IsSynthesizedMemberToBeExcluded(type)) - { - (_excludedCompilerGeneratedTypes ??= new List()).Add(type.FullName); - } - else - { - InstrumentType(type); - } - } + InstrumentType(type); } + } + } - // Fixup the custom tracker class constructor, according to all instrumented types - if (_customTrackerRegisterUnloadEventsMethod == null) - { - _customTrackerRegisterUnloadEventsMethod = new MethodReference( - nameof(ModuleTrackerTemplate.RegisterUnloadEvents), module.TypeSystem.Void, _customTrackerTypeDef); - } + // Fixup the custom tracker class constructor, according to all instrumented types + if (_customTrackerRegisterUnloadEventsMethod == null) + { + _customTrackerRegisterUnloadEventsMethod = new MethodReference( + nameof(ModuleTrackerTemplate.RegisterUnloadEvents), module.TypeSystem.Void, _customTrackerTypeDef); + } - Instruction lastInstr = _customTrackerClassConstructorIl.Body.Instructions.Last(); + Instruction lastInstr = _customTrackerClassConstructorIl.Body.Instructions.Last(); - if (!containsAppContext) - { - // For "normal" cases, where the instrumented assembly is not the core library, we add a call to - // RegisterUnloadEvents to the static constructor of the generated custom tracker. Due to static - // initialization constraints, the core library is handled separately below. - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Call, _customTrackerRegisterUnloadEventsMethod)); - } + if (!containsAppContext) + { + // For "normal" cases, where the instrumented assembly is not the core library, we add a call to + // RegisterUnloadEvents to the static constructor of the generated custom tracker. Due to static + // initialization constraints, the core library is handled separately below. + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Call, _customTrackerRegisterUnloadEventsMethod)); + } - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldc_I4, _result.HitCandidates.Count)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Newarr, module.TypeSystem.Int32)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerHitsArray)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldstr, _result.HitsFilePath)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerHitsFilePath)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(_parameters.SingleHit ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerSingleHit)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldc_I4_1)); - _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerFlushHitFile)); - - if (containsAppContext) + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldc_I4, _result.HitCandidates.Count)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Newarr, module.TypeSystem.Int32)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerHitsArray)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldstr, _result.HitsFilePath)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerHitsFilePath)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(_parameters.SingleHit ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerSingleHit)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldc_I4_1)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerFlushHitFile)); + + if (containsAppContext) + { + // Handle the core library by instrumenting System.AppContext.OnProcessExit to directly call + // the UnloadModule method of the custom tracker type. This avoids loops between the static + // initialization of the custom tracker and the static initialization of the hosting AppDomain + // (which for the core library case will be instrumented code). + var eventArgsType = new TypeReference(nameof(System), nameof(EventArgs), module, module.TypeSystem.CoreLibrary); + var customTrackerUnloadModule = new MethodReference(nameof(ModuleTrackerTemplate.UnloadModule), module.TypeSystem.Void, _customTrackerTypeDef); + customTrackerUnloadModule.Parameters.Add(new ParameterDefinition(module.TypeSystem.Object)); + customTrackerUnloadModule.Parameters.Add(new ParameterDefinition(eventArgsType)); + + var appContextType = new TypeReference(nameof(System), nameof(AppContext), module, module.TypeSystem.CoreLibrary); + MethodDefinition onProcessExitMethod = new MethodReference("OnProcessExit", module.TypeSystem.Void, appContextType).Resolve(); + ILProcessor onProcessExitIl = onProcessExitMethod.Body.GetILProcessor(); + + // Put the OnProcessExit body inside try/finally to ensure the call to the UnloadModule. + Instruction lastInst = onProcessExitMethod.Body.Instructions.Last(); + var firstNullParam = Instruction.Create(OpCodes.Ldnull); + var secondNullParam = Instruction.Create(OpCodes.Ldnull); + var callUnload = Instruction.Create(OpCodes.Call, customTrackerUnloadModule); + onProcessExitIl.InsertAfter(lastInst, firstNullParam); + onProcessExitIl.InsertAfter(firstNullParam, secondNullParam); + onProcessExitIl.InsertAfter(secondNullParam, callUnload); + var endFinally = Instruction.Create(OpCodes.Endfinally); + onProcessExitIl.InsertAfter(callUnload, endFinally); + Instruction ret = onProcessExitIl.Create(OpCodes.Ret); + Instruction leaveAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); + onProcessExitIl.InsertAfter(endFinally, ret); + foreach (Instruction inst in onProcessExitMethod.Body.Instructions.ToArray()) + { + // Patch ret to leave after the finally + if (inst.OpCode == OpCodes.Ret && inst != ret) { - // Handle the core library by instrumenting System.AppContext.OnProcessExit to directly call - // the UnloadModule method of the custom tracker type. This avoids loops between the static - // initialization of the custom tracker and the static initialization of the hosting AppDomain - // (which for the core library case will be instrumented code). - var eventArgsType = new TypeReference(nameof(System), nameof(EventArgs), module, module.TypeSystem.CoreLibrary); - var customTrackerUnloadModule = new MethodReference(nameof(ModuleTrackerTemplate.UnloadModule), module.TypeSystem.Void, _customTrackerTypeDef); - customTrackerUnloadModule.Parameters.Add(new ParameterDefinition(module.TypeSystem.Object)); - customTrackerUnloadModule.Parameters.Add(new ParameterDefinition(eventArgsType)); - - var appContextType = new TypeReference(nameof(System), nameof(AppContext), module, module.TypeSystem.CoreLibrary); - MethodDefinition onProcessExitMethod = new MethodReference("OnProcessExit", module.TypeSystem.Void, appContextType).Resolve(); - ILProcessor onProcessExitIl = onProcessExitMethod.Body.GetILProcessor(); - - // Put the OnProcessExit body inside try/finally to ensure the call to the UnloadModule. - Instruction lastInst = onProcessExitMethod.Body.Instructions.Last(); - var firstNullParam = Instruction.Create(OpCodes.Ldnull); - var secondNullParam = Instruction.Create(OpCodes.Ldnull); - var callUnload = Instruction.Create(OpCodes.Call, customTrackerUnloadModule); - onProcessExitIl.InsertAfter(lastInst, firstNullParam); - onProcessExitIl.InsertAfter(firstNullParam, secondNullParam); - onProcessExitIl.InsertAfter(secondNullParam, callUnload); - var endFinally = Instruction.Create(OpCodes.Endfinally); - onProcessExitIl.InsertAfter(callUnload, endFinally); - Instruction ret = onProcessExitIl.Create(OpCodes.Ret); - Instruction leaveAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); - onProcessExitIl.InsertAfter(endFinally, ret); - foreach (Instruction inst in onProcessExitMethod.Body.Instructions.ToArray()) - { - // Patch ret to leave after the finally - if (inst.OpCode == OpCodes.Ret && inst != ret) - { - Instruction leaveBodyInstAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); - Instruction prevInst = inst.Previous; - onProcessExitMethod.Body.Instructions.Remove(inst); - onProcessExitIl.InsertAfter(prevInst, leaveBodyInstAfterFinally); - } - } - var handler = new ExceptionHandler(ExceptionHandlerType.Finally) - { - TryStart = onProcessExitIl.Body.Instructions.First(), - TryEnd = firstNullParam, - HandlerStart = firstNullParam, - HandlerEnd = ret - }; - - onProcessExitMethod.Body.ExceptionHandlers.Add(handler); + Instruction leaveBodyInstAfterFinally = onProcessExitIl.Create(OpCodes.Leave, ret); + Instruction prevInst = inst.Previous; + onProcessExitMethod.Body.Instructions.Remove(inst); + onProcessExitIl.InsertAfter(prevInst, leaveBodyInstAfterFinally); } - - module.Write(stream, new WriterParameters { WriteSymbols = true }); } + var handler = new ExceptionHandler(ExceptionHandlerType.Finally) + { + TryStart = onProcessExitIl.Body.Instructions.First(), + TryEnd = firstNullParam, + HandlerStart = firstNullParam, + HandlerEnd = ret + }; + + onProcessExitMethod.Body.ExceptionHandlers.Add(handler); } + + module.Write(stream, new WriterParameters { WriteSymbols = true }); } private void AddCustomModuleTrackerToModule(ModuleDefinition module) @@ -864,52 +856,52 @@ public IMetadataImporter GetMetadataImporter(ModuleDefinition module) private class CoreLibMetadataImporter : IMetadataImporter { - private readonly ModuleDefinition module; - private readonly DefaultMetadataImporter defaultMetadataImporter; + private readonly ModuleDefinition _module; + private readonly DefaultMetadataImporter _defaultMetadataImporter; public CoreLibMetadataImporter(ModuleDefinition module) { - this.module = module; - defaultMetadataImporter = new DefaultMetadataImporter(module); + _module = module; + _defaultMetadataImporter = new DefaultMetadataImporter(module); } public AssemblyNameReference ImportReference(AssemblyNameReference reference) { - return defaultMetadataImporter.ImportReference(reference); + return _defaultMetadataImporter.ImportReference(reference); } public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context) { - TypeReference importedRef = defaultMetadataImporter.ImportReference(type, context); - importedRef.GetElementType().Scope = module.TypeSystem.CoreLibrary; + TypeReference importedRef = _defaultMetadataImporter.ImportReference(type, context); + importedRef.GetElementType().Scope = _module.TypeSystem.CoreLibrary; return importedRef; } public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context) { - FieldReference importedRef = defaultMetadataImporter.ImportReference(field, context); - importedRef.FieldType.GetElementType().Scope = module.TypeSystem.CoreLibrary; + FieldReference importedRef = _defaultMetadataImporter.ImportReference(field, context); + importedRef.FieldType.GetElementType().Scope = _module.TypeSystem.CoreLibrary; return importedRef; } public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context) { - MethodReference importedRef = defaultMetadataImporter.ImportReference(method, context); - importedRef.DeclaringType.GetElementType().Scope = module.TypeSystem.CoreLibrary; + MethodReference importedRef = _defaultMetadataImporter.ImportReference(method, context); + importedRef.DeclaringType.GetElementType().Scope = _module.TypeSystem.CoreLibrary; foreach (ParameterDefinition parameter in importedRef.Parameters) { - if (parameter.ParameterType.Scope == module.TypeSystem.CoreLibrary) + if (parameter.ParameterType.Scope == _module.TypeSystem.CoreLibrary) { continue; } - parameter.ParameterType.GetElementType().Scope = module.TypeSystem.CoreLibrary; + parameter.ParameterType.GetElementType().Scope = _module.TypeSystem.CoreLibrary; } - if (importedRef.ReturnType.Scope != module.TypeSystem.CoreLibrary) + if (importedRef.ReturnType.Scope != _module.TypeSystem.CoreLibrary) { - importedRef.ReturnType.GetElementType().Scope = module.TypeSystem.CoreLibrary; + importedRef.ReturnType.GetElementType().Scope = _module.TypeSystem.CoreLibrary; } return importedRef; diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index b538143be..600fe91b1 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -26,8 +26,8 @@ internal static class ModuleTrackerTemplate public static int[] HitsArray; public static bool SingleHit; public static bool FlushHitFile; - private static readonly bool _enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) ? result == 1 : false; - private static readonly string _sessionId = Guid.NewGuid().ToString(); + private static readonly bool s_enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) && result == 1; + private static readonly string s_sessionId = Guid.NewGuid().ToString(); static ModuleTrackerTemplate() { @@ -83,100 +83,94 @@ public static void UnloadModule(object sender, EventArgs e) { // The same module can be unloaded multiple times in the same process via different app domains. // Use a global mutex to ensure no concurrent access. - using (var mutex = new Mutex(true, Path.GetFileNameWithoutExtension(HitsFilePath) + "_Mutex", out bool createdNew)) + using var mutex = new Mutex(true, Path.GetFileNameWithoutExtension(HitsFilePath) + "_Mutex", out bool createdNew); + if (!createdNew) { - if (!createdNew) - { - mutex.WaitOne(); - } + mutex.WaitOne(); + } - if (FlushHitFile) + if (FlushHitFile) + { + try { - try - { - // Claim the current hits array and reset it to prevent double-counting scenarios. - int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); + // Claim the current hits array and reset it to prevent double-counting scenarios. + int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); - WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender ?? "null"}'"); - WriteLog($"Flushing hit file '{HitsFilePath}'"); + WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender ?? "null"}'"); + WriteLog($"Flushing hit file '{HitsFilePath}'"); - bool failedToCreateNewHitsFile = false; - try + bool failedToCreateNewHitsFile = false; + try + { + using var fs = new FileStream(HitsFilePath, FileMode.CreateNew); + using var bw = new BinaryWriter(fs); + bw.Write(hitsArray.Length); + foreach (int hitCount in hitsArray) { - using (var fs = new FileStream(HitsFilePath, FileMode.CreateNew)) - using (var bw = new BinaryWriter(fs)) - { - bw.Write(hitsArray.Length); - foreach (int hitCount in hitsArray) - { - bw.Write(hitCount); - } - } + bw.Write(hitCount); } - catch (Exception ex) + } + catch (Exception ex) + { + WriteLog($"Failed to create new hits file '{HitsFilePath}' -> '{ex.Message}'"); + failedToCreateNewHitsFile = true; + } + + if (failedToCreateNewHitsFile) + { + // Update the number of hits by adding value on disk with the ones on memory. + // This path should be triggered only in the case of multiple AppDomain unloads. + using var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + using var br = new BinaryReader(fs); + using var bw = new BinaryWriter(fs); + int hitsLength = br.ReadInt32(); + WriteLog($"Current hits found '{hitsLength}'"); + + if (hitsLength != hitsArray.Length) { - WriteLog($"Failed to create new hits file '{HitsFilePath}' -> '{ex.Message}'"); - failedToCreateNewHitsFile = true; + throw new InvalidOperationException($"{HitsFilePath} has {hitsLength} entries but on memory {nameof(HitsArray)} has {hitsArray.Length}"); } - if (failedToCreateNewHitsFile) + for (int i = 0; i < hitsLength; ++i) { - // Update the number of hits by adding value on disk with the ones on memory. - // This path should be triggered only in the case of multiple AppDomain unloads. - using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) - using (var br = new BinaryReader(fs)) - using (var bw = new BinaryWriter(fs)) + int oldHitCount = br.ReadInt32(); + bw.Seek(-sizeof(int), SeekOrigin.Current); + if (SingleHit) + { + bw.Write(hitsArray[i] + oldHitCount > 0 ? 1 : 0); + } + else { - int hitsLength = br.ReadInt32(); - WriteLog($"Current hits found '{hitsLength}'"); - - if (hitsLength != hitsArray.Length) - { - throw new InvalidOperationException($"{HitsFilePath} has {hitsLength} entries but on memory {nameof(HitsArray)} has {hitsArray.Length}"); - } - - for (int i = 0; i < hitsLength; ++i) - { - int oldHitCount = br.ReadInt32(); - bw.Seek(-sizeof(int), SeekOrigin.Current); - if (SingleHit) - { - bw.Write(hitsArray[i] + oldHitCount > 0 ? 1 : 0); - } - else - { - bw.Write(hitsArray[i] + oldHitCount); - } - } + bw.Write(hitsArray[i] + oldHitCount); } } + } - WriteHits(sender); + WriteHits(sender); - WriteLog($"Hit file '{HitsFilePath}' flushed, size {new FileInfo(HitsFilePath).Length}"); - WriteLog("--------------------------------"); - } - catch (Exception ex) - { - WriteLog(ex.ToString()); - throw; - } + WriteLog($"Hit file '{HitsFilePath}' flushed, size {new FileInfo(HitsFilePath).Length}"); + WriteLog("--------------------------------"); + } + catch (Exception ex) + { + WriteLog(ex.ToString()); + throw; } - - // On purpose this is not under a try-finally: it is better to have an exception if there was any error writing the hits file - // this case is relevant when instrumenting corelib since multiple processes can be running against the same instrumented dll. - mutex.ReleaseMutex(); } + + // On purpose this is not under a try-finally: it is better to have an exception if there was any error writing the hits file + // this case is relevant when instrumenting corelib since multiple processes can be running against the same instrumented dll. + mutex.ReleaseMutex(); } private static void WriteHits(object sender) { - if (_enableLog) + if (s_enableLog) { var currentAssembly = Assembly.GetExecutingAssembly(); var location = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(currentAssembly.Location), "TrackersHitsLog")); location.Create(); - string logFile = Path.Combine(location.FullName, $"{Path.GetFileName(currentAssembly.Location)}_{DateTime.UtcNow.Ticks}_{_sessionId}.txt"); + string logFile = Path.Combine(location.FullName, $"{Path.GetFileName(currentAssembly.Location)}_{DateTime.UtcNow.Ticks}_{s_sessionId}.txt"); using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (var log = new FileStream(logFile, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None)) using (var logWriter = new StreamWriter(log)) @@ -195,12 +189,12 @@ private static void WriteHits(object sender) private static void WriteLog(string logText) { - if (_enableLog) + if (s_enableLog) { // We don't set path as global var to keep benign possible errors inside try/catch // I'm not sure that location will be ok in every scenario string location = Assembly.GetExecutingAssembly().Location; - File.AppendAllText(Path.Combine(Path.GetDirectoryName(location), Path.GetFileName(location) + "_tracker.txt"), $"[{DateTime.UtcNow} S:{_sessionId} T:{Thread.CurrentThread.ManagedThreadId}]{logText}{Environment.NewLine}"); + File.AppendAllText(Path.Combine(Path.GetDirectoryName(location), Path.GetFileName(location) + "_tracker.txt"), $"[{DateTime.UtcNow} S:{s_sessionId} T:{Thread.CurrentThread.ManagedThreadId}]{logText}{Environment.NewLine}"); } } } diff --git a/src/coverlet.core/Instrumentation/ReachabilityHelper.cs b/src/coverlet.core/Instrumentation/ReachabilityHelper.cs index dee555a21..1b4840d85 100644 --- a/src/coverlet.core/Instrumentation/ReachabilityHelper.cs +++ b/src/coverlet.core/Instrumentation/ReachabilityHelper.cs @@ -100,9 +100,9 @@ private readonly struct BranchInstruction /// /// Returns true if this branch has multiple targets. /// - public bool HasMultiTargets => _TargetOffset == -1; + public bool HasMultiTargets => _targetOffset == -1; - private readonly int _TargetOffset; + private readonly int _targetOffset; /// /// Target of the branch, assuming it has a single target. @@ -118,11 +118,11 @@ public int TargetOffset throw new InvalidOperationException($"{HasMultiTargets} is true"); } - return _TargetOffset; + return _targetOffset; } } - private readonly ImmutableArray _TargetOffsets; + private readonly ImmutableArray _targetOffsets; /// /// Targets of the branch, assuming it has multiple targets. @@ -138,15 +138,15 @@ public ImmutableArray TargetOffsets throw new InvalidOperationException($"{HasMultiTargets} is false"); } - return _TargetOffsets; + return _targetOffsets; } } public BranchInstruction(int offset, int targetOffset) { Offset = offset; - _TargetOffset = targetOffset; - _TargetOffsets = ImmutableArray.Empty; + _targetOffset = targetOffset; + _targetOffsets = ImmutableArray.Empty; } public BranchInstruction(int offset, ImmutableArray targetOffset) @@ -157,8 +157,8 @@ public BranchInstruction(int offset, ImmutableArray targetOffset) } Offset = offset; - _TargetOffset = -1; - _TargetOffsets = targetOffset; + _targetOffset = -1; + _targetOffsets = targetOffset; } public override string ToString() @@ -169,7 +169,7 @@ public override string ToString() /// OpCodes that transfer control code, even if they do not /// introduce branch points. /// - private static readonly ImmutableHashSet BRANCH_OPCODES = + private static readonly ImmutableHashSet s_branchOpCodes = ImmutableHashSet.CreateRange( new[] { @@ -224,7 +224,7 @@ public override string ToString() /// OpCodes that unconditionally transfer control, so there /// is not "fall through" branch target. /// - private static readonly ImmutableHashSet UNCONDITIONAL_BRANCH_OPCODES = + private static readonly ImmutableHashSet s_unconditionalBranchOpCodes = ImmutableHashSet.CreateRange( new[] { @@ -235,11 +235,11 @@ public override string ToString() } ); - private readonly ImmutableHashSet DoesNotReturnMethods; + private readonly ImmutableHashSet _doesNotReturnMethods; private ReachabilityHelper(ImmutableHashSet doesNotReturnMethods) { - DoesNotReturnMethods = doesNotReturnMethods; + _doesNotReturnMethods = doesNotReturnMethods; } /// @@ -372,7 +372,7 @@ public ImmutableArray FindUnreachableIL(Collection.Empty; } @@ -406,7 +406,7 @@ public ImmutableArray FindUnreachableIL(Collection multiTargetOffsets) = GetInstructionTargets(i, exceptionHandlers); @@ -453,7 +453,7 @@ private static (int? SingleTargetOffset, ImmutableArray MultiTargetOffsets) { // it's any of the B.*(_S)? or Leave(_S)? instructions - if (UNCONDITIONAL_BRANCH_OPCODES.Contains(i.OpCode)) + if (s_unconditionalBranchOpCodes.Contains(i.OpCode)) { multiTargetOffsets = ImmutableArray.Empty; singleTargetOffset = targetInstr.Offset; @@ -527,7 +527,7 @@ private static (int? SingleTargetOffset, ImmutableArray MultiTargetOffsets) /// /// Calculates which ranges of IL are unreachable, given blocks which have head and tail reachability calculated. /// - private ImmutableArray DetermineUnreachableRanges(ImmutableArray blocks, int lastInstructionOffset) + private static ImmutableArray DetermineUnreachableRanges(ImmutableArray blocks, int lastInstructionOffset) { ImmutableArray.Builder ret = ImmutableArray.CreateBuilder(); @@ -580,7 +580,7 @@ private ImmutableArray DetermineUnreachableRanges(ImmutableArr /// /// "Tail reachability" will have already been determined in CreateBlocks. /// - private void DetermineHeadReachability(ImmutableArray blocks) + private static void DetermineHeadReachability(ImmutableArray blocks) { var blockLookup = blocks.ToImmutableDictionary(b => b.StartOffset); @@ -791,7 +791,7 @@ private bool DoesNotReturn(Instruction instr) return false; } - return DoesNotReturnMethods.Contains(mtd.MetadataToken); + return _doesNotReturnMethods.Contains(mtd.MetadataToken); } /// diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 0daff6a69..57571df9a 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Toni Solarin-Sodara +// Copyright (c) Toni Solarin-Sodara // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; @@ -111,7 +111,7 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran { var condition = new XElement("condition"); condition.Add(new XAttribute("number", entry.Key)); - condition.Add(new XAttribute("type", entry.Value.Count() > 2 ? "switch" : "jump")); // Just guessing here + condition.Add(new XAttribute("type", entry.Value.Count > 2 ? "switch" : "jump")); // Just guessing here condition.Add(new XAttribute("coverage", $"{summary.CalculateBranchCoverage(entry.Value).Percent.ToString(CultureInfo.InvariantCulture)}%")); conditions.Add(condition); } @@ -119,7 +119,6 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran line.Add(conditions); } - lines.Add(line); classLines.Add(line); } @@ -234,4 +233,4 @@ private static string GetRelativePathFromBase(IEnumerable basePaths, str return path; } } -} \ No newline at end of file +} diff --git a/src/coverlet.core/Reporters/TeamCityReporter.cs b/src/coverlet.core/Reporters/TeamCityReporter.cs index 365f20e46..8ccb0d997 100644 --- a/src/coverlet.core/Reporters/TeamCityReporter.cs +++ b/src/coverlet.core/Reporters/TeamCityReporter.cs @@ -39,7 +39,7 @@ public string Report(CoverageResult result, ISourceRootTranslator sourceRootTran return stringBuilder.ToString(); } - private void OutputLineCoverage(CoverageDetails coverageDetails, StringBuilder builder) + private static void OutputLineCoverage(CoverageDetails coverageDetails, StringBuilder builder) { // The number of covered lines OutputTeamCityServiceMessage("CodeCoverageAbsLCovered", coverageDetails.Covered, builder); @@ -48,7 +48,7 @@ private void OutputLineCoverage(CoverageDetails coverageDetails, StringBuilder b OutputTeamCityServiceMessage("CodeCoverageAbsLTotal", coverageDetails.Total, builder); } - private void OutputBranchCoverage(CoverageDetails coverageDetails, StringBuilder builder) + private static void OutputBranchCoverage(CoverageDetails coverageDetails, StringBuilder builder) { // The number of covered branches OutputTeamCityServiceMessage("CodeCoverageAbsBCovered", coverageDetails.Covered, builder); @@ -57,7 +57,7 @@ private void OutputBranchCoverage(CoverageDetails coverageDetails, StringBuilder OutputTeamCityServiceMessage("CodeCoverageAbsBTotal", coverageDetails.Total, builder); } - private void OutputMethodCoverage(CoverageDetails coverageDetails, StringBuilder builder) + private static void OutputMethodCoverage(CoverageDetails coverageDetails, StringBuilder builder) { // The number of covered methods OutputTeamCityServiceMessage("CodeCoverageAbsMCovered", coverageDetails.Covered, builder); @@ -66,7 +66,7 @@ private void OutputMethodCoverage(CoverageDetails coverageDetails, StringBuilder OutputTeamCityServiceMessage("CodeCoverageAbsMTotal", coverageDetails.Total, builder); } - private void OutputTeamCityServiceMessage(string key, double value, StringBuilder builder) + private static void OutputTeamCityServiceMessage(string key, double value, StringBuilder builder) { builder.AppendLine($"##teamcity[buildStatisticValue key='{key}' value='{value.ToString("0.##", new CultureInfo("en-US"))}']"); } diff --git a/src/coverlet.core/Symbols/CecilSymbolHelper.cs b/src/coverlet.core/Symbols/CecilSymbolHelper.cs index 23789124a..a718c82bb 100644 --- a/src/coverlet.core/Symbols/CecilSymbolHelper.cs +++ b/src/coverlet.core/Symbols/CecilSymbolHelper.cs @@ -20,8 +20,8 @@ internal class CecilSymbolHelper : ICecilSymbolHelper { private const int StepOverLineCode = 0xFEEFEE; // Create single instance, we cannot collide because we use full method name as key - private readonly ConcurrentDictionary _compilerGeneratedBranchesToExclude = new ConcurrentDictionary(); - private readonly ConcurrentDictionary> _sequencePointOffsetToSkip = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary _compilerGeneratedBranchesToExclude = new(); + private readonly ConcurrentDictionary> _sequencePointOffsetToSkip = new(); // In case of nested compiler generated classes, only the root one presents the CompilerGenerated attribute. // So let's search up to the outermost declaring type to find the attribute @@ -83,7 +83,8 @@ private static bool IsMoveNextInsideEnumerator(MethodDefinition methodDefinition { return false; } - if (methodDefinition.DeclaringType.CustomAttributes.Count(ca => ca.AttributeType.FullName == typeof(CompilerGeneratedAttribute).FullName) > 0) + + if (methodDefinition.DeclaringType.CustomAttributes.Any(ca => ca.AttributeType.FullName == typeof(CompilerGeneratedAttribute).FullName)) { foreach (InterfaceImplementation implementedInterface in methodDefinition.DeclaringType.Interfaces) { @@ -465,7 +466,6 @@ private static bool SkipGeneratedBranchesForAwaitForeach(List instr CheckIfExceptionThrown(instructions, instruction, currentIndex) || CheckThrownExceptionType(instructions, instruction, currentIndex); - // The pattern for the "should we stay in the loop or not?", which we don't // want to skip (so we have no method to try to find it), looks like this: // @@ -477,7 +477,6 @@ private static bool SkipGeneratedBranchesForAwaitForeach(List instr // the "call" and branch, but it's the same idea either way: branch // if GetResult() returned true. - static bool CheckForAsyncEnumerator(List instructions, Instruction instruction, int currentIndex) { // We're looking for the following pattern, which checks whether a @@ -506,7 +505,6 @@ static bool CheckForAsyncEnumerator(List instructions, Instruction return false; } - static bool CheckIfExceptionThrown(List instructions, Instruction instruction, int currentIndex) { // Here, we want to find a pattern where we're checking whether a @@ -564,7 +562,6 @@ instructions[j].Operand is MethodReference callRef && return false; } - static bool CheckThrownExceptionType(List instructions, Instruction instruction, int currentIndex) { // In this case, we're looking for a branch generated by the compiler to @@ -617,7 +614,6 @@ private static bool SkipGeneratedBranchesForAwaitUsing(List instruc return CheckForSkipDisposal(instructions, instruction, currentIndex) || CheckForCleanup(instructions, instruction, currentIndex); - static bool CheckForSkipDisposal(List instructions, Instruction instruction, int currentIndex) { // The async state machine generated for an "await using" contains a branch @@ -727,7 +723,6 @@ instructions[i].Operand is FieldDefinition reloadedField && return false; } - static bool CheckForCleanup(List instructions, Instruction instruction, int currentIndex) { // The pattern we're looking for here is this: @@ -812,7 +807,6 @@ private static bool SkipGeneratedBranchesForAsyncIterator(List inst return CheckForStateSwitch(instructions, instruction, currentIndex) || DisposeCheck(instructions, instruction, currentIndex); - static bool CheckForStateSwitch(List instructions, Instruction instruction, int currentIndex) { // The pattern we're looking for here is this one: @@ -890,7 +884,7 @@ static bool DisposeCheck(List instructions, Instruction instruction } } - private bool SkipGeneratedBranchesForEnumeratorCancellationAttribute(List instructions, Instruction instruction) + private static bool SkipGeneratedBranchesForEnumeratorCancellationAttribute(List instructions, Instruction instruction) { // For async-enumerable methods an additional cancellation token despite the default one can be passed. // The EnumeratorCancellation attribute marks the parameter whose value is received by GetAsyncEnumerator(CancellationToken). diff --git a/src/coverlet.msbuild.tasks/CoverageResultTask.cs b/src/coverlet.msbuild.tasks/CoverageResultTask.cs index 642d2a92b..23a29f7a5 100644 --- a/src/coverlet.msbuild.tasks/CoverageResultTask.cs +++ b/src/coverlet.msbuild.tasks/CoverageResultTask.cs @@ -152,9 +152,9 @@ public override bool Execute() if (Threshold.Contains(',')) { IEnumerable thresholdValues = Threshold.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()); - if (thresholdValues.Count() != thresholdTypeFlagQueue.Count()) + if (thresholdValues.Count() != thresholdTypeFlagQueue.Count) { - throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count()}) and values count ({thresholdValues.Count()}) doesn't match"); + throw new Exception($"Threshold type flag count ({thresholdTypeFlagQueue.Count}) and values count ({thresholdValues.Count()}) doesn't match"); } foreach (string threshold in thresholdValues) diff --git a/src/coverlet.msbuild.tasks/InstrumentationTask.cs b/src/coverlet.msbuild.tasks/InstrumentationTask.cs index e84327dd0..2ec4910da 100644 --- a/src/coverlet.msbuild.tasks/InstrumentationTask.cs +++ b/src/coverlet.msbuild.tasks/InstrumentationTask.cs @@ -112,13 +112,9 @@ public override bool Execute() CoveragePrepareResult prepareResult = coverage.PrepareModules(); InstrumenterState = new TaskItem(System.IO.Path.GetTempFileName()); - using (Stream instrumentedStateFile = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write)) - { - using (Stream serializedState = CoveragePrepareResult.Serialize(prepareResult)) - { - serializedState.CopyTo(instrumentedStateFile); - } - } + using Stream instrumentedStateFile = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write); + using Stream serializedState = CoveragePrepareResult.Serialize(prepareResult); + serializedState.CopyTo(instrumentedStateFile); } catch (Exception ex) { diff --git a/test/coverlet.collector.tests/CoverletSettingsParserTests.cs b/test/coverlet.collector.tests/CoverletSettingsParserTests.cs index 0e3286e06..191bdb232 100644 --- a/test/coverlet.collector.tests/CoverletSettingsParserTests.cs +++ b/test/coverlet.collector.tests/CoverletSettingsParserTests.cs @@ -188,14 +188,14 @@ public void ParseShouldUseDefaultFormatWhenNoFormatSpecified(string formats) Assert.Equal(defaultFormat, coverletSettings.ReportFormats[0]); } - private void CreateCoverletNodes(XmlDocument doc, XmlElement configElement, string nodeSetting, string nodeValue) + private static void CreateCoverletNodes(XmlDocument doc, XmlElement configElement, string nodeSetting, string nodeValue) { XmlNode node = doc.CreateNode("element", nodeSetting, string.Empty); node.InnerText = nodeValue; configElement.AppendChild(node); } - private void CreateCoverletNullInnerTextNodes(XmlDocument doc, XmlElement configElement, string nodeSetting) + private static void CreateCoverletNullInnerTextNodes(XmlDocument doc, XmlElement configElement, string nodeSetting) { XmlNode node = doc.CreateNode("element", nodeSetting, string.Empty); node.InnerText = null; diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.cs b/test/coverlet.core.tests/Coverage/CoverageTests.cs index e6bf461eb..06be97c72 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.cs @@ -13,7 +13,7 @@ namespace Coverlet.Core.Tests { public partial class CoverageTests { - private readonly Mock _mockLogger = new Mock(); + private readonly Mock _mockLogger = new(); [Fact] public void TestCoverage() diff --git a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs index efc0138a8..8cb5eca7f 100644 --- a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs +++ b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs @@ -23,7 +23,7 @@ namespace Coverlet.Core.Tests { static class TestInstrumentationHelper { - private static IServiceProvider _processWideContainer; + private static IServiceProvider s_processWideContainer; /// /// caller sample: TestInstrumentationHelper.GenerateHtmlReport(result, sourceFileFilter: @"+**\Samples\Instrumentation.cs"); @@ -64,9 +64,9 @@ public static CoverageResult GetCoverageResult(string filePath) { Assert.DoesNotContain("not found for module: ", message); }); - _processWideContainer.GetRequiredService().SetLogger(logger.Object); + s_processWideContainer.GetRequiredService().SetLogger(logger.Object); var coveragePrepareResultLoaded = CoveragePrepareResult.Deserialize(result); - var coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, _processWideContainer.GetService(), new FileSystem(), new SourceRootTranslator(new Mock().Object, new FileSystem())); + var coverage = new Coverage(coveragePrepareResultLoaded, logger.Object, s_processWideContainer.GetService(), new FileSystem(), new SourceRootTranslator(new Mock().Object, new FileSystem())); return coverage.GetCoverageResult(); } @@ -121,7 +121,7 @@ public static async Task Run(Func callM // Instrument module var coverage = new Coverage(newPath, parameters, new Logger(logFile), - _processWideContainer.GetService(), _processWideContainer.GetService(), _processWideContainer.GetService(), _processWideContainer.GetService()); + s_processWideContainer.GetService(), s_processWideContainer.GetService(), s_processWideContainer.GetService(), s_processWideContainer.GetService()); CoveragePrepareResult prepareResult = coverage.PrepareModules(); Assert.Single(prepareResult.Results); @@ -153,7 +153,7 @@ public static async Task Run(Func callM private static void SetTestContainer(string testModule = null, bool disableRestoreModules = false) { - LazyInitializer.EnsureInitialized(ref _processWideContainer, () => + LazyInitializer.EnsureInitialized(ref s_processWideContainer, () => { var serviceCollection = new ServiceCollection(); serviceCollection.AddTransient(); @@ -291,7 +291,7 @@ public override void RestoreOriginalModules() public abstract class ExternalProcessExecutionTest { - protected FunctionExecutor FunctionExecutor = new FunctionExecutor( + protected FunctionExecutor FunctionExecutor = new( o => { o.StartInfo.RedirectStandardError = true; diff --git a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs index 031b8a5d0..d0883ae61 100644 --- a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs +++ b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs @@ -15,7 +15,7 @@ namespace Coverlet.Core.Helpers.Tests public class InstrumentationHelperTests { private readonly InstrumentationHelper _instrumentationHelper = - new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(typeof(InstrumentationHelperTests).Assembly.Location, new Mock().Object, new FileSystem())); + new(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock().Object, new SourceRootTranslator(typeof(InstrumentationHelperTests).Assembly.Location, new Mock().Object, new FileSystem())); [Fact] public void TestGetDependencies() diff --git a/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs b/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs index 907f5cc66..189648834 100644 --- a/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs +++ b/test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs @@ -26,12 +26,12 @@ namespace Coverlet.Core.Instrumentation.Tests { public class InstrumenterTests : IDisposable { - private readonly Mock _mockLogger = new Mock(); - private Action disposeAction; + private readonly Mock _mockLogger = new(); + private Action _disposeAction; public void Dispose() { - disposeAction?.Invoke(); + _disposeAction?.Invoke(); } [ConditionalFact] @@ -192,9 +192,7 @@ public void TestInstrument_ClassesWithMethodWithCustomExcludeAttributeAreExclude Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); -#pragma warning disable CS0612 // Type or member is obsolete bool found = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::Method(System.String)")); -#pragma warning restore CS0612 // Type or member is obsolete Assert.False(found, "Method decorated with with exclude attribute should be excluded"); instrumenterTest.Directory.Delete(true); @@ -211,14 +209,10 @@ public void TestInstrument_ClassesWithPropertyWithCustomExcludeAttributeAreExclu Document doc = result.Documents.Values.FirstOrDefault(d => Path.GetFileName(d.Path) == "Samples.cs"); Assert.NotNull(doc); -#pragma warning disable CS0612 // Type or member is obsolete bool getFound = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::get_Property()")); -#pragma warning restore CS0612 // Type or member is obsolete Assert.False(getFound, "Property getter decorated with with exclude attribute should be excluded"); -#pragma warning disable CS0612 // Type or member is obsolete bool setFound = doc.Lines.Values.Any(l => l.Method.Equals($"System.String Coverlet.Core.Samples.Tests.{testClassName}::set_Property()")); -#pragma warning restore CS0612 // Type or member is obsolete Assert.False(setFound, "Property setter decorated with with exclude attribute should be excluded"); instrumenterTest.Directory.Delete(true); @@ -587,7 +581,7 @@ public int SampleMethod() string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(tempDirectory); - disposeAction = () => Directory.Delete(tempDirectory, true); + _disposeAction = () => Directory.Delete(tempDirectory, true); var partialMockFileSystem = new Mock(); partialMockFileSystem.CallBase = true; diff --git a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs index c0b8dd282..7cd5f2943 100644 --- a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs +++ b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs @@ -30,7 +30,7 @@ public void Dispose() public class ModuleTrackerTemplateTests : ExternalProcessExecutionTest { - private static readonly Task _success = Task.FromResult(0); + private static readonly Task s_success = Task.FromResult(0); [Fact] public void HitsFileCorrectlyWritten() @@ -44,7 +44,7 @@ public void HitsFileCorrectlyWritten() int[] expectedHitsArray = new[] { 1, 2, 0, 3 }; Assert.Equal(expectedHitsArray, ReadHitsFile()); - return _success; + return s_success; }); } @@ -57,7 +57,7 @@ public void HitsFileWithDifferentNumberOfEntriesCausesExceptionOnUnload() WriteHitsFile(new[] { 1, 2, 3 }); ModuleTrackerTemplate.HitsArray = new[] { 1 }; Assert.Throws(() => ModuleTrackerTemplate.UnloadModule(null, null)); - return _success; + return s_success; }); } @@ -94,7 +94,7 @@ static void HitIndex(object index) } } - return _success; + return s_success; }); } @@ -113,7 +113,7 @@ public void MultipleSequentialUnloadsHaveCorrectTotalData() int[] expectedHitsArray = new[] { 0, 4, 4, 4 }; Assert.Equal(expectedHitsArray, ReadHitsFile()); - return _success; + return s_success; }); } @@ -149,32 +149,28 @@ public void MutexBlocksMultipleWriters() } - private void WriteHitsFile(int[] hitsArray) + private static void WriteHitsFile(int[] hitsArray) { - using (var fs = new FileStream(ModuleTrackerTemplate.HitsFilePath, FileMode.Create)) - using (var bw = new BinaryWriter(fs)) + using var fs = new FileStream(ModuleTrackerTemplate.HitsFilePath, FileMode.Create); + using var bw = new BinaryWriter(fs); + bw.Write(hitsArray.Length); + foreach (int hitCount in hitsArray) { - bw.Write(hitsArray.Length); - foreach (int hitCount in hitsArray) - { - bw.Write(hitCount); - } + bw.Write(hitCount); } } - private int[] ReadHitsFile() + private static int[] ReadHitsFile() { - using (var fs = new FileStream(ModuleTrackerTemplate.HitsFilePath, FileMode.Open)) - using (var br = new BinaryReader(fs)) + using var fs = new FileStream(ModuleTrackerTemplate.HitsFilePath, FileMode.Open); + using var br = new BinaryReader(fs); + int[] hitsArray = new int[br.ReadInt32()]; + for (int i = 0; i < hitsArray.Length; ++i) { - int[] hitsArray = new int[br.ReadInt32()]; - for (int i = 0; i < hitsArray.Length; ++i) - { - hitsArray[i] = br.ReadInt32(); - } - - return hitsArray; + hitsArray[i] = br.ReadInt32(); } + + return hitsArray; } } } diff --git a/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs b/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs index 7ea79155b..8b6e46c6d 100644 --- a/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs +++ b/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs @@ -41,7 +41,7 @@ public void GetBranchPoints_OneBranch() // assert Assert.NotNull(points); - Assert.Equal(2, points.Count()); + Assert.Equal(2, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(0, points[0].Path); Assert.Equal(1, points[1].Path); @@ -61,7 +61,7 @@ public void GetBranchPoints_Using_Where_GeneratedBranchesIgnored() // act System.Collections.Generic.IReadOnlyList points = _cecilSymbolHelper.GetBranchPoints(method); - Assert.Equal(2, points.Count()); + Assert.Equal(2, points.Count); } [Fact] @@ -89,7 +89,7 @@ public void GetBranchPoints_TwoBranch() // assert Assert.NotNull(points); - Assert.Equal(4, points.Count()); + Assert.Equal(4, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(points[2].Offset, points[3].Offset); Assert.Equal(28, points[0].StartLine); @@ -108,7 +108,7 @@ public void GetBranchPoints_CompleteIf() // assert Assert.NotNull(points); - Assert.Equal(2, points.Count()); + Assert.Equal(2, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(35, points[0].StartLine); Assert.Equal(35, points[1].StartLine); @@ -127,7 +127,7 @@ public void GetBranchPoints_Switch() // assert Assert.NotNull(points); - Assert.Equal(4, points.Count()); + Assert.Equal(4, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(points[0].Offset, points[2].Offset); Assert.Equal(3, points[3].Path); @@ -150,7 +150,7 @@ public void GetBranchPoints_SwitchWithDefault() // assert Assert.NotNull(points); - Assert.Equal(4, points.Count()); + Assert.Equal(4, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(points[0].Offset, points[2].Offset); Assert.Equal(3, points[3].Path); @@ -173,7 +173,7 @@ public void GetBranchPoints_SwitchWithBreaks() // assert Assert.NotNull(points); - Assert.Equal(4, points.Count()); + Assert.Equal(4, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(points[0].Offset, points[2].Offset); Assert.Equal(3, points[3].Path); @@ -196,7 +196,7 @@ public void GetBranchPoints_SwitchWithMultipleCases() // assert Assert.NotNull(points); - Assert.Equal(4, points.Count()); + Assert.Equal(4, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(points[0].Offset, points[2].Offset); Assert.Equal(points[0].Offset, points[3].Offset); @@ -351,7 +351,7 @@ public void GetBranchPoints_IgnoresMostBranchesIn_AwaitForeachStateMachine() // We do expect there to be a two-way branch (stay in the loop or not?) on // the line containing "await foreach". Assert.NotNull(points); - Assert.Equal(2, points.Count()); + Assert.Equal(2, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(204, points[0].StartLine); Assert.Equal(204, points[1].StartLine); @@ -375,7 +375,7 @@ public void GetBranchPoints_IgnoresMostBranchesIn_AwaitForeachStateMachine_WithB // containing "await foreach" and the other being the "if" statement inside // the loop. Assert.NotNull(points); - Assert.Equal(4, points.Count()); + Assert.Equal(4, points.Count); Assert.Equal(points[0].Offset, points[1].Offset); Assert.Equal(points[2].Offset, points[3].Offset); Assert.Equal(219, points[0].StartLine); @@ -399,7 +399,7 @@ public void GetBranchPoints_IgnoresExtraBranchesIn_AsyncIteratorStateMachine() // assert // We do expect the "for" loop to be a branch with two branch points, but that's it. Assert.NotNull(points); - Assert.Equal(2, points.Count()); + Assert.Equal(2, points.Count); Assert.Equal(237, points[0].StartLine); Assert.Equal(237, points[1].StartLine); } diff --git a/test/coverlet.integration.tests/BaseTest.cs b/test/coverlet.integration.tests/BaseTest.cs index 0417b1d35..c10372c02 100644 --- a/test/coverlet.integration.tests/BaseTest.cs +++ b/test/coverlet.integration.tests/BaseTest.cs @@ -24,7 +24,7 @@ public enum BuildConfiguration public abstract class BaseTest { - private static int _folderSuffix = 0; + private static int s_folderSuffix; protected BuildConfiguration GetAssemblyBuildConfiguration() { @@ -67,7 +67,7 @@ private protected string GetPackageVersion(string filter) private protected ClonedTemplateProject CloneTemplateProject(bool cleanupOnDispose = true, string testSDKVersion = "16.5.0") { - DirectoryInfo finalRoot = Directory.CreateDirectory($"{Guid.NewGuid().ToString("N").Substring(0, 6)}{Interlocked.Increment(ref _folderSuffix)}"); + DirectoryInfo finalRoot = Directory.CreateDirectory($"{Guid.NewGuid().ToString("N")[..6]}{Interlocked.Increment(ref s_folderSuffix)}"); foreach (string file in (Directory.GetFiles($"../../../../coverlet.integration.template", "*.cs") .Union(Directory.GetFiles($"../../../../coverlet.integration.template", "*.csproj") .Union(Directory.GetFiles($"../../../../coverlet.integration.template", "nuget.config"))))) From 3c1124e88fe03cac8728ba992da1794f92a84cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Tue, 15 Mar 2022 10:33:17 +0100 Subject: [PATCH 04/16] Wrong coverage for await foreach with generic method (#1312) --- Documentation/Changelog.md | 5 +++++ src/coverlet.core/Symbols/CecilSymbolHelper.cs | 13 +++++++++---- .../Coverage/CoverageTests.AsyncForeach.cs | 10 +++++++--- .../Samples/Instrumentation.AsyncForeach.cs | 8 ++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index 5c551ceec..c04c509ae 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed +-Await foreach has wrong branch coverage when method is generic [#1210](https://github.com/coverlet-coverage/coverlet/issues/1210) + ## Release date 2022-02-06 ### Packages coverlet.msbuild 3.1.2 diff --git a/src/coverlet.core/Symbols/CecilSymbolHelper.cs b/src/coverlet.core/Symbols/CecilSymbolHelper.cs index a718c82bb..f5f8458b0 100644 --- a/src/coverlet.core/Symbols/CecilSymbolHelper.cs +++ b/src/coverlet.core/Symbols/CecilSymbolHelper.cs @@ -496,8 +496,11 @@ static bool CheckForAsyncEnumerator(List instructions, Instruction (instructions[currentIndex - 2].OpCode == OpCodes.Ldarg || instructions[currentIndex - 2].OpCode == OpCodes.Ldarg_0) && instructions[currentIndex - 1].OpCode == OpCodes.Ldfld && - instructions[currentIndex - 1].Operand is FieldDefinition field && - IsCompilerGenerated(field) && field.FieldType.FullName.StartsWith("System.Collections.Generic.IAsyncEnumerator")) + ( + (instructions[currentIndex - 1].Operand is FieldDefinition field && IsCompilerGenerated(field) && field.FieldType.FullName.StartsWith("System.Collections.Generic.IAsyncEnumerator")) || + (instructions[currentIndex - 1].Operand is FieldReference fieldRef && IsCompilerGenerated(fieldRef.Resolve()) && fieldRef.FieldType.FullName.StartsWith("System.Collections.Generic.IAsyncEnumerator")) + ) + ) { return true; } @@ -538,8 +541,10 @@ static bool CheckIfExceptionThrown(List instructions, Instruction i for (int i = currentIndex - 1; i >= minFieldIndex; --i) { if (instructions[i].OpCode == OpCodes.Ldfld && - instructions[i].Operand is FieldDefinition field && - IsCompilerGenerated(field) && field.FieldType.FullName == "System.Object") + ( + (instructions[i].Operand is FieldDefinition field && IsCompilerGenerated(field) && field.FieldType.FullName == "System.Object") || + (instructions[i].Operand is FieldReference fieldRef && IsCompilerGenerated(fieldRef.Resolve()) && fieldRef.FieldType.FullName == "System.Object") + )) { // We expect the call to GetResult() to be no more than four // instructions before the loading of the field's value. diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs index 8e3a2bc91..77450d19b 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.AsyncForeach.cs @@ -24,6 +24,7 @@ public void AsyncForeach() int res = ((ValueTask)instance.SumWithATwist(AsyncEnumerable.Range(1, 5))).GetAwaiter().GetResult(); res += ((ValueTask)instance.Sum(AsyncEnumerable.Range(1, 3))).GetAwaiter().GetResult(); res += ((ValueTask)instance.SumEmpty()).GetAwaiter().GetResult(); + ((ValueTask)instance.GenericAsyncForeach(AsyncEnumerable.Range(1, 3))).GetAwaiter().GetResult(); return Task.CompletedTask; }, persistPrepareResultToFile: pathSerialize[0]); @@ -43,7 +44,9 @@ public void AsyncForeach() // Sum(IAsyncEnumerable) (34, 1), (35, 1), (37, 9), (38, 3), (39, 3), (40, 3), (42, 1), (43, 1), // SumEmpty() - (47, 1), (48, 1), (50, 3), (51, 0), (52, 0), (53, 0), (55, 1), (56, 1) + (47, 1), (48, 1), (50, 3), (51, 0), (52, 0), (53, 0), (55, 1), (56, 1), + // GenericAsyncForeach + (59,1), (60, 9), (61, 3), (62, 3), (63, 3), (64, 1) ) .AssertBranchesCovered(BuildConfiguration.Debug, // SumWithATwist(IAsyncEnumerable) @@ -53,9 +56,10 @@ public void AsyncForeach() // SumEmpty() // If we never entered the loop, that's a branch not taken, which is // what we want to see. - (50, 0, 1), (50, 1, 0) + (50, 0, 1), (50, 1, 0), + (60, 0, 1), (60, 1, 3) ) - .ExpectedTotalNumberOfBranches(BuildConfiguration.Debug, 4); + .ExpectedTotalNumberOfBranches(BuildConfiguration.Debug, 5); } finally { diff --git a/test/coverlet.core.tests/Samples/Instrumentation.AsyncForeach.cs b/test/coverlet.core.tests/Samples/Instrumentation.AsyncForeach.cs index 961f9df31..d8765cfd2 100644 --- a/test/coverlet.core.tests/Samples/Instrumentation.AsyncForeach.cs +++ b/test/coverlet.core.tests/Samples/Instrumentation.AsyncForeach.cs @@ -54,5 +54,13 @@ async public ValueTask SumEmpty() return sum; } + + public async ValueTask GenericAsyncForeach(IAsyncEnumerable ints) + { + await foreach (int obj in ints) + { + await Task.Delay(1); + } + } } } From ebbf0424495de04e334beaabf626244fe9b80b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Tue, 15 Mar 2022 21:23:55 +0100 Subject: [PATCH 05/16] imp + test + changelog (#1306) --- Documentation/Changelog.md | 1 + .../Instrumentation/Instrumenter.cs | 20 ++++++++++++++ ...erageTests.ExcludeFromCoverageAttribute.cs | 27 +++++++++++++++++++ ...mentation.ExcludeFromCoverage.Issue1302.cs | 18 +++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 test/coverlet.core.tests/Samples/Instrumentation.ExcludeFromCoverage.Issue1302.cs diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index c04c509ae..ebd49c508 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -Await foreach has wrong branch coverage when method is generic [#1210](https://github.com/coverlet-coverage/coverlet/issues/1210) +-ExcludeFromCodeCoverage attribute on local functions ignores lambda expression [#1302](https://github.com/coverlet-coverage/coverlet/issues/1302) ## Release date 2022-02-06 ### Packages diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 51b18c07c..42a1a1835 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -45,6 +45,7 @@ internal class Instrumenter private List _excludedSourceFiles; private List _branchesInCompiledGeneratedClass; private List<(MethodDefinition, int)> _excludedMethods; + private List _excludedLambdaMethods; private List _excludedCompilerGeneratedTypes; private readonly string[] _doesNotReturnAttributes; private ReachabilityHelper _reachabilityHelper; @@ -500,12 +501,18 @@ private void InstrumentType(TypeDefinition type) continue; } + if (_excludedLambdaMethods != null && _excludedLambdaMethods.Contains(method.FullName)) + { + continue; + } + if (!customAttributes.Any(IsExcludeAttribute)) { InstrumentMethod(method); } else { + (_excludedLambdaMethods ??= new List()).AddRange(CollectLambdaMethodsInsideLocalFunction(method)); (_excludedMethods ??= new List<(MethodDefinition, int)>()).Add((method, ordinal)); } } @@ -842,6 +849,19 @@ internal bool IsSynthesizedNameOf(string name, string methodName, int methodOrdi (name.IndexOf($"<{methodName}>g__") != -1 && name.IndexOf($"|{methodOrdinal}_") != -1); } + private static IEnumerable CollectLambdaMethodsInsideLocalFunction(MethodDefinition methodDefinition) + { + if (!methodDefinition.Name.Contains(">g__")) yield break; + + foreach (Instruction instruction in methodDefinition.Body.Instructions.ToList()) + { + if (instruction.OpCode == OpCodes.Ldftn && instruction.Operand is MethodReference mr && mr.Name.Contains(">b__")) + { + yield return mr.FullName; + } + } + } + /// /// A custom importer created specifically to allow the instrumentation of System.Private.CoreLib by /// removing the external references to netstandard that are generated when instrumenting a typical diff --git a/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs b/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs index e989c3838..bead5b913 100644 --- a/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs +++ b/test/coverlet.core.tests/Coverage/CoverageTests.ExcludeFromCoverageAttribute.cs @@ -277,5 +277,32 @@ public void ExcludeFromCodeCoverageAutoGeneratedGet() File.Delete(path); } } + + [Fact] + public void ExcludeFromCodeCoverage_Issue1302() + { + string path = Path.GetTempFileName(); + try + { + FunctionExecutor.Run(async (string[] pathSerialize) => + { + CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run(instance => + { + instance.Run(); + return Task.CompletedTask; + }, persistPrepareResultToFile: pathSerialize[0]); + + return 0; + }, new string[] { path }); + + TestInstrumentationHelper.GetCoverageResult(path) + .Document("Instrumentation.ExcludeFromCoverage.Issue1302.cs") + .AssertNonInstrumentedLines(BuildConfiguration.Debug, 10, 13); + } + finally + { + File.Delete(path); + } + } } } diff --git a/test/coverlet.core.tests/Samples/Instrumentation.ExcludeFromCoverage.Issue1302.cs b/test/coverlet.core.tests/Samples/Instrumentation.ExcludeFromCoverage.Issue1302.cs new file mode 100644 index 000000000..8bf8dd2d4 --- /dev/null +++ b/test/coverlet.core.tests/Samples/Instrumentation.ExcludeFromCoverage.Issue1302.cs @@ -0,0 +1,18 @@ +using System; + +namespace Coverlet.Core.Samples.Tests +{ + public class Issue1302 + { + public void Run() + { + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + static Func LocalFunction() + { + return myString => myString.Length == 10; + } + + LocalFunction(); + } + } +} From 104bf16a0c9eb11c18b347fef67409d2eb66b196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Mon, 18 Apr 2022 08:55:00 +0200 Subject: [PATCH 06/16] return relative path as sourcelink for codegenerators (#1323) --- src/coverlet.core/Coverage.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs index b53cdf5d8..25a415b5b 100644 --- a/src/coverlet.core/Coverage.cs +++ b/src/coverlet.core/Coverage.cs @@ -513,8 +513,12 @@ private string GetSourceLinkUrl(Dictionary sourceLinkDocuments, string replacement = Path.Combine(relativePathOfBestMatch, Path.GetFileName(document)); replacement = replacement.Replace('\\', '/'); - url = sourceLinkDocuments[keyWithBestMatch]; - return url.Replace("*", replacement); + if (sourceLinkDocuments.TryGetValue(keyWithBestMatch, out url)) + { + return url.Replace("*", replacement); + } + + return document; } } } From a41c365589f3aa2d604f94c82c1acf0e1927b6c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Fri, 22 Apr 2022 09:36:36 +0200 Subject: [PATCH 07/16] Missing change log (#1326) Missing change log --- Documentation/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index ebd49c508..f61ee169b 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Fixed +-Source Link for code generators fails [#1322](https://github.com/coverlet-coverage/coverlet/issues/1322) -Await foreach has wrong branch coverage when method is generic [#1210](https://github.com/coverlet-coverage/coverlet/issues/1210) -ExcludeFromCodeCoverage attribute on local functions ignores lambda expression [#1302](https://github.com/coverlet-coverage/coverlet/issues/1302) From 7219aee6a45b6dc080f7778771d6f1ddc0fc8605 Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Mon, 9 May 2022 09:09:08 -0700 Subject: [PATCH 08/16] Ensure trailing slash in (#1327) Ensure trailing slash in --- DeterministicBuild.targets | 2 +- Documentation/DeterministicBuild.md | 2 +- .../MSBuild/DeterministicBuild/DeterministicBuild.targets | 2 +- .../VSTest/DeterministicBuild/DeterministicBuild.targets | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DeterministicBuild.targets b/DeterministicBuild.targets index 78052937d..13208d103 100644 --- a/DeterministicBuild.targets +++ b/DeterministicBuild.targets @@ -9,7 +9,7 @@ https://github.com/dotnet/sourcelink/issues/572 --> - + - + - + - + Date: Wed, 8 Jun 2022 20:05:29 +0200 Subject: [PATCH 09/16] Update README.md (#1347) Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e008ec44a..c60b9d37c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Coverlet can be used through three different *drivers* Coverlet supports only SDK-style projects https://docs.microsoft.com/en-us/visualstudio/msbuild/how-to-use-project-sdk?view=vs-2019 -### VSTest Integration (preferred due to [known issue](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test) supports only .NET Core application) +### VSTest Integration (preferred due to [known issue](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test)) ### Installation ```bash From e50e24d4545f8c9c918423812131ea0f9b67cd20 Mon Sep 17 00:00:00 2001 From: George Vanburgh <1670176+georgevanburgh@users.noreply.github.com> Date: Fri, 24 Jun 2022 08:37:05 +0100 Subject: [PATCH 10/16] Add some more Roslyn generated file suffixes (#1352) Add some more Roslyn generated file suffixes --- .../Helpers/InstrumentationHelper.cs | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index 70dd7b677..a95327322 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -178,12 +178,13 @@ public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDoc Document document = metadataReader.GetDocument(docHandle); string docName = _sourceRootTranslator.ResolveFilePath(metadataReader.GetString(document.Name)); Guid languageGuid = metadataReader.GetGuid(document.Language); + // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach // We exlude from the check the autogenerated source file(i.e. source generators) // We exclude special F# construct https://github.com/coverlet-coverage/coverlet/issues/1145 - if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs") && + if (!_fileSystem.Exists(docName) && !IsGeneratedDocumentName(docName) && !IsUnknownModuleInFSharpAssembly(languageGuid, docName)) { return (false, docName); @@ -449,6 +450,35 @@ private static bool IsAssembly(string filePath) } } + // Follow the same rules that exist in Microsoft.CodeAnalysis + // https://sourceroslyn.io/#Microsoft.CodeAnalysis/InternalUtilities/GeneratedCodeUtilities.cs,55bff725ec9f1338,references + private static bool IsGeneratedDocumentName(string docPath) + { + if (!string.IsNullOrEmpty(docPath)) + { + string fileName = Path.GetFileName(docPath); + if (fileName.StartsWith("TemporaryGeneratedFile_", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + string extension = Path.GetExtension(fileName); + if (!string.IsNullOrEmpty(extension)) + { + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(docPath); + if (fileNameWithoutExtension.EndsWith(".designer", StringComparison.OrdinalIgnoreCase) || + fileNameWithoutExtension.EndsWith(".generated", StringComparison.OrdinalIgnoreCase) || + fileNameWithoutExtension.EndsWith(".g", StringComparison.OrdinalIgnoreCase) || + fileNameWithoutExtension.EndsWith(".g.i", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + } + + return false; + } + private static bool IsUnknownModuleInFSharpAssembly(Guid languageGuid, string docName) { // https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md#document-table-0x30 From 1e85144217bc47a5438c259bb71890c7e3219905 Mon Sep 17 00:00:00 2001 From: Maciej Klemarczyk Date: Mon, 27 Jun 2022 11:23:48 +0200 Subject: [PATCH 11/16] Handle PDB location when project build externally (#1354) Handle PDB location when project build externally --- .../Abstractions/ISourceRootTranslator.cs | 1 + .../Helpers/InstrumentationHelper.cs | 22 +++++++++++++++++-- .../Helpers/SourceRootTranslator.cs | 11 ++++++++++ .../Helpers/InstrumentationHelperTests.cs | 17 +++++++++++++- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/coverlet.core/Abstractions/ISourceRootTranslator.cs b/src/coverlet.core/Abstractions/ISourceRootTranslator.cs index f64907b7d..4af6cfddf 100644 --- a/src/coverlet.core/Abstractions/ISourceRootTranslator.cs +++ b/src/coverlet.core/Abstractions/ISourceRootTranslator.cs @@ -8,6 +8,7 @@ namespace Coverlet.Core.Abstractions { internal interface ISourceRootTranslator { + bool AddMappingInCache(string originalFileName, string targetFileName); string ResolveFilePath(string originalFileName); string ResolveDeterministicPath(string originalFileName); IReadOnlyList ResolvePathRoot(string pathRoot); diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index a95327322..fcf9f4fcf 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -90,14 +90,32 @@ public bool HasPdb(string module, out bool embedded) if (entry.Type == DebugDirectoryEntryType.CodeView) { CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); - if (_sourceRootTranslator.ResolveFilePath(codeViewData.Path) == $"{Path.GetFileNameWithoutExtension(module)}.pdb") + string modulePdbFileName = $"{Path.GetFileNameWithoutExtension(module)}.pdb"; + if (_sourceRootTranslator.ResolveFilePath(codeViewData.Path) == modulePdbFileName) { // PDB is embedded embedded = true; return true; } - return _fileSystem.Exists(_sourceRootTranslator.ResolveFilePath(codeViewData.Path)); + if (_fileSystem.Exists(_sourceRootTranslator.ResolveFilePath(codeViewData.Path))) + { + // local PDB is located within original build location + embedded = false; + return true; + } + + string localPdbFileName = Path.Combine(Path.GetDirectoryName(module), modulePdbFileName); + if (_fileSystem.Exists(localPdbFileName)) + { + // local PDB is located within same folder as module + embedded = false; + + // mapping need to be registered in _sourceRootTranslator to use that discovery + _sourceRootTranslator.AddMappingInCache(codeViewData.Path, localPdbFileName); + + return true; + } } } diff --git a/src/coverlet.core/Helpers/SourceRootTranslator.cs b/src/coverlet.core/Helpers/SourceRootTranslator.cs index 4d50fbf81..5bdef76a0 100644 --- a/src/coverlet.core/Helpers/SourceRootTranslator.cs +++ b/src/coverlet.core/Helpers/SourceRootTranslator.cs @@ -108,6 +108,17 @@ private Dictionary> LoadSourceRootMapping(string return mapping; } + public bool AddMappingInCache(string originalFileName, string targetFileName) + { + if (_resolutionCacheFiles != null && _resolutionCacheFiles.ContainsKey(originalFileName)) + { + return false; + } + + (_resolutionCacheFiles ??= new Dictionary()).Add(originalFileName, targetFileName); + return true; + } + public IReadOnlyList ResolvePathRoot(string pathRoot) { return _sourceRootMapping.TryGetValue(pathRoot, out List sourceRootMapping) ? sourceRootMapping.AsReadOnly() : null; diff --git a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs index d0883ae61..c6feee244 100644 --- a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs +++ b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs @@ -54,12 +54,27 @@ public void EmbeddedPortablePDPHasLocalSource_AllDocumentsExist_ReturnsTrue() } [Fact] - public void TestHasPdb() + public void TestHasPdbOfLocalAssembly() { Assert.True(_instrumentationHelper.HasPdb(typeof(InstrumentationHelperTests).Assembly.Location, out bool embeddedPdb)); Assert.False(embeddedPdb); } + [Fact] + public void TestHasPdbOfExternalAssembly() + { + string testAssemblyLocation = GetType().Assembly.Location; + + string externalAssemblyFileName = Path.Combine( + Path.GetDirectoryName(testAssemblyLocation), + "TestAssets", + "75d9f96508d74def860a568f426ea4a4.dll" + ); + + Assert.True(_instrumentationHelper.HasPdb(externalAssemblyFileName, out bool embeddedPdb)); + Assert.False(embeddedPdb); + } + [Fact] public void TestBackupOriginalModule() { From e11c14d11fa5b442f754246ce39346ce51703ff4 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 29 Jul 2022 15:49:30 +0200 Subject: [PATCH 12/16] Added InstrumentModulesWithoutLocalSources setting (#1360) * ignore not available sources * remove debug.assert * readded assert * added setting to allow instrumentation of modules without local sources * Update src/coverlet.console/Program.cs Co-authored-by: Peter Liljenberg * Update CoberturaReporter.cs removed obsolete Debug.Assert Co-authored-by: adfrth5 Co-authored-by: Peter Liljenberg --- .../DataCollection/CoverageWrapper.cs | 3 ++- .../DataCollection/CoverletSettings.cs | 6 ++++++ .../DataCollection/CoverletSettingsParser.cs | 13 +++++++++++++ .../Utilities/CoverletConstants.cs | 1 + src/coverlet.console/Program.cs | 4 +++- src/coverlet.core/Coverage.cs | 2 ++ src/coverlet.core/Instrumentation/Instrumenter.cs | 5 +++++ src/coverlet.core/Reporters/CoberturaReporter.cs | 3 --- src/coverlet.msbuild.tasks/InstrumentationTask.cs | 3 +++ 9 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/coverlet.collector/DataCollection/CoverageWrapper.cs b/src/coverlet.collector/DataCollection/CoverageWrapper.cs index 9018ee387..0f8dc4287 100644 --- a/src/coverlet.collector/DataCollection/CoverageWrapper.cs +++ b/src/coverlet.collector/DataCollection/CoverageWrapper.cs @@ -33,7 +33,8 @@ public Coverage CreateCoverage(CoverletSettings settings, ILogger coverletLogger UseSourceLink = settings.UseSourceLink, SkipAutoProps = settings.SkipAutoProps, DoesNotReturnAttributes = settings.DoesNotReturnAttributes, - DeterministicReport = settings.DeterministicReport + DeterministicReport = settings.DeterministicReport, + InstrumentModulesWithoutLocalSources = settings.InstrumentModulesWithoutLocalSources }; return new Coverage( diff --git a/src/coverlet.collector/DataCollection/CoverletSettings.cs b/src/coverlet.collector/DataCollection/CoverletSettings.cs index bf04e6326..7a23e0a5e 100644 --- a/src/coverlet.collector/DataCollection/CoverletSettings.cs +++ b/src/coverlet.collector/DataCollection/CoverletSettings.cs @@ -81,6 +81,11 @@ internal class CoverletSettings /// public bool DeterministicReport { get; set; } + /// + /// Instruments modules even if the sources from the PDBs can't be resolved. + /// + public bool InstrumentModulesWithoutLocalSources { get; set; } + public override string ToString() { var builder = new StringBuilder(); @@ -98,6 +103,7 @@ public override string ToString() builder.AppendFormat("SkipAutoProps: '{0}'", SkipAutoProps); builder.AppendFormat("DoesNotReturnAttributes: '{0}'", string.Join(",", DoesNotReturnAttributes ?? Enumerable.Empty())); builder.AppendFormat("DeterministicReport: '{0}'", DeterministicReport); + builder.AppendFormat("InstrumentModulesWithoutLocalSources: '{0}'", InstrumentModulesWithoutLocalSources); return builder.ToString(); } diff --git a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs index 4440b24d8..b1a77b1dc 100644 --- a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs +++ b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs @@ -48,6 +48,7 @@ public CoverletSettings Parse(XmlElement configurationElement, IEnumerable + /// Parse InstrumentModulesWithoutLocalSources flag + /// + /// Configuration element + /// InstrumentModulesWithoutLocalSources flag + private static bool ParseInstrumentModulesWithoutLocalSources(XmlElement configurationElement) + { + XmlElement instrumentModulesWithoutLocalSourcesElement = configurationElement[CoverletConstants.InstrumentModulesWithoutLocalSources]; + bool.TryParse(instrumentModulesWithoutLocalSourcesElement?.InnerText, out bool instrumentModulesWithoutLocalSources); + return instrumentModulesWithoutLocalSources; + } + /// /// Parse include test assembly flag /// diff --git a/src/coverlet.collector/Utilities/CoverletConstants.cs b/src/coverlet.collector/Utilities/CoverletConstants.cs index 5aff53cfb..a8bd770e7 100644 --- a/src/coverlet.collector/Utilities/CoverletConstants.cs +++ b/src/coverlet.collector/Utilities/CoverletConstants.cs @@ -26,5 +26,6 @@ internal static class CoverletConstants public const string SkipAutoProps = "SkipAutoProps"; public const string DoesNotReturnAttributesElementName = "DoesNotReturnAttribute"; public const string DeterministicReport = "DeterministicReport"; + public const string InstrumentModulesWithoutLocalSources = "InstrumentModulesWithoutLocalSources"; } } diff --git a/src/coverlet.console/Program.cs b/src/coverlet.console/Program.cs index 25f5f7350..a80f6ff31 100644 --- a/src/coverlet.console/Program.cs +++ b/src/coverlet.console/Program.cs @@ -70,6 +70,7 @@ static int Main(string[] args) CommandOption mergeWith = app.Option("--merge-with", "Path to existing coverage result to merge.", CommandOptionType.SingleValue); CommandOption useSourceLink = app.Option("--use-source-link", "Specifies whether to use SourceLink URIs in place of file system paths.", CommandOptionType.NoValue); CommandOption doesNotReturnAttributes = app.Option("--does-not-return-attribute", "Attributes that mark methods that do not return.", CommandOptionType.MultipleValue); + CommandOption instrumentModulesWithoutLocalSources = app.Option("--instrument-modules-without-local-sources", "Specifies whether modules should be instrumented even if the sources from the PDBs can't be found locally.", CommandOptionType.NoValue); app.OnExecute(() => { @@ -97,7 +98,8 @@ static int Main(string[] args) MergeWith = mergeWith.Value(), UseSourceLink = useSourceLink.HasValue(), SkipAutoProps = skipAutoProp.HasValue(), - DoesNotReturnAttributes = doesNotReturnAttributes.Values.ToArray() + DoesNotReturnAttributes = doesNotReturnAttributes.Values.ToArray(), + InstrumentModulesWithoutLocalSources = instrumentModulesWithoutLocalSources.HasValue(), }; ISourceRootTranslator sourceRootTranslator = serviceProvider.GetRequiredService(); diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs index 25a415b5b..d0357997e 100644 --- a/src/coverlet.core/Coverage.cs +++ b/src/coverlet.core/Coverage.cs @@ -43,6 +43,8 @@ internal class CoverageParameters public bool SkipAutoProps { get; set; } [DataMember] public bool DeterministicReport { get; set; } + [DataMember] + public bool InstrumentModulesWithoutLocalSources { get; set; } } internal class Coverage diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 42a1a1835..36d195c50 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -94,6 +94,11 @@ public bool CanInstrument() { if (_instrumentationHelper.HasPdb(_module, out bool embeddedPdb)) { + if (this._parameters.InstrumentModulesWithoutLocalSources) + { + return true; + } + if (embeddedPdb) { if (_instrumentationHelper.EmbeddedPortablePdbHasLocalSource(_module, out string firstNotFoundDocument)) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 57571df9a..e3d299fda 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -227,9 +227,6 @@ private static string GetRelativePathFromBase(IEnumerable basePaths, str return path.Substring(basePath.Length); } } - - Debug.Assert(false, "Unexpected, we should find at least one path starts with one pre-build roots list"); - return path; } } diff --git a/src/coverlet.msbuild.tasks/InstrumentationTask.cs b/src/coverlet.msbuild.tasks/InstrumentationTask.cs index 2ec4910da..b43f152d4 100644 --- a/src/coverlet.msbuild.tasks/InstrumentationTask.cs +++ b/src/coverlet.msbuild.tasks/InstrumentationTask.cs @@ -47,6 +47,8 @@ public class InstrumentationTask : BaseTask public bool DeterministicReport { get; set; } + public bool InstrumentModulesWithoutLocalSources { get; set; } + [Output] public ITaskItem InstrumenterState { get; set; } @@ -99,6 +101,7 @@ public override bool Execute() UseSourceLink = UseSourceLink, SkipAutoProps = SkipAutoProps, DeterministicReport = DeterministicReport, + InstrumentModulesWithoutLocalSources = InstrumentModulesWithoutLocalSources, DoesNotReturnAttributes = DoesNotReturnAttribute?.Split(',') }; From 2b8a4565b101ca70c3eaa9b5228c449dd3b81ad1 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Wed, 28 Sep 2022 09:40:43 +0200 Subject: [PATCH 13/16] Update documentation with new feature `InstrumentModulesWithoutLocalSources` (#1385) Update documentation with new feature `InstrumentModulesWithoutLocalSources` --- Documentation/GlobalTool.md | 1 + Documentation/MSBuildIntegration.md | 4 ++++ Documentation/VSTestIntegration.md | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/GlobalTool.md b/Documentation/GlobalTool.md index 231da2ff5..64d659d63 100644 --- a/Documentation/GlobalTool.md +++ b/Documentation/GlobalTool.md @@ -38,6 +38,7 @@ Options: --merge-with Path to existing coverage result to merge. --use-source-link Specifies whether to use SourceLink URIs in place of file system paths. --does-not-return-attribute Attributes that mark methods that do not return. + --instrument-modules-without-local-sources Specifies whether modules should be instrumented even if the sources from the PDBs can't be found locally. ``` NB. For a [multiple value] options you have to specify values multiple times i.e. diff --git a/Documentation/MSBuildIntegration.md b/Documentation/MSBuildIntegration.md index bde9f364e..1848c3e65 100644 --- a/Documentation/MSBuildIntegration.md +++ b/Documentation/MSBuildIntegration.md @@ -181,6 +181,10 @@ You can also include coverage of the test assembly itself by setting `/p:Include Neither track nor record auto-implemented properties. Syntax: `/p:SkipAutoProps=true` +### Instrument module wihtout local sources file. + +Syntax: `/p:InstrumentModulesWithoutLocalSources=true` + ### Methods that do not return Methods that do not return can be marked with attributes to cause statements after them to be excluded from coverage. diff --git a/Documentation/VSTestIntegration.md b/Documentation/VSTestIntegration.md index 07c17a092..b01e4ee9c 100644 --- a/Documentation/VSTestIntegration.md +++ b/Documentation/VSTestIntegration.md @@ -97,7 +97,8 @@ These are a list of options that are supported by coverlet. These can be specifi | IncludeTestAssembly | Include coverage of the test assembly. | | SkipAutoProps | Neither track nor record auto-implemented properties. | | DoesNotReturnAttribute | Methods marked with these attributes are known not to return, statements following them will be excluded from coverage | -| DeterministicReport | Generates deterministic report in context of deterministic build. Take a look at [documentation](DeterministicBuild.md) for further informations. | +| DeterministicReport | Generates deterministic report in context of deterministic build. Take a look at [documentation](DeterministicBuild.md) for further informations. | +| InstrumentModulesWithoutLocalSources | Specifies whether modules should be instrumented even if the sources from the PDBs can't be found locally. | How to specify these options via runsettings? @@ -119,6 +120,7 @@ How to specify these options via runsettings? true true false + false From 5637470aa9ba8ce07a6ffdfce995d11888ae5b73 Mon Sep 17 00:00:00 2001 From: Jakub Chocholowicz <59966772+jakubch1@users.noreply.github.com> Date: Fri, 7 Oct 2022 17:01:28 +0200 Subject: [PATCH 14/16] Make targets changes linear (#1388) Make targets changes linear --- .../Instrumentation/Instrumenter.cs | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 36d195c50..e3ff94a46 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -572,6 +572,7 @@ private void InstrumentIL(MethodDefinition method) int index = 0; int count = processor.Body.Instructions.Count; IReadOnlyList branchPoints = _cecilSymbolHelper.GetBranchPoints(method); + IDictionary targetsMap = new Dictionary(); System.Collections.Immutable.ImmutableArray unreachableRanges = _reachabilityHelper.FindUnreachableIL(processor.Body.Instructions, processor.Body.ExceptionHandlers); int currentUnreachableRangeIx = 0; for (int n = 0; n < count; n++) @@ -611,11 +612,7 @@ private void InstrumentIL(MethodDefinition method) } Instruction firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, sequencePoint); - foreach (Instruction bodyInstruction in processor.Body.Instructions) - ReplaceInstructionTarget(bodyInstruction, currentInstruction, firstInjectedInstrumentedOpCode); - - foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers) - ReplaceExceptionHandlerBoundary(handler, currentInstruction, firstInjectedInstrumentedOpCode); + targetsMap.Add(currentInstruction.Offset, firstInjectedInstrumentedOpCode); index += 2; } @@ -632,11 +629,8 @@ private void InstrumentIL(MethodDefinition method) continue; Instruction firstInjectedInstrumentedOpCode = AddInstrumentationCode(method, processor, currentInstruction, branchTarget); - foreach (Instruction bodyInstruction in processor.Body.Instructions) - ReplaceInstructionTarget(bodyInstruction, currentInstruction, firstInjectedInstrumentedOpCode); - - foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers) - ReplaceExceptionHandlerBoundary(handler, currentInstruction, firstInjectedInstrumentedOpCode); + if (!targetsMap.ContainsKey(currentInstruction.Offset)) + targetsMap.Add(currentInstruction.Offset, firstInjectedInstrumentedOpCode); index += 2; } @@ -644,6 +638,12 @@ private void InstrumentIL(MethodDefinition method) index++; } + foreach (Instruction bodyInstruction in processor.Body.Instructions) + ReplaceInstructionTarget(bodyInstruction, targetsMap); + + foreach (ExceptionHandler handler in processor.Body.ExceptionHandlers) + ReplaceExceptionHandlerBoundary(handler, targetsMap); + method.Body.OptimizeMacros(); } @@ -744,42 +744,41 @@ private Instruction AddInstrumentationInstructions(MethodDefinition method, ILPr return indxInstr; } - private static void ReplaceInstructionTarget(Instruction instruction, Instruction oldTarget, Instruction newTarget) + private static void ReplaceInstructionTarget(Instruction instruction, IDictionary targetsMap) { if (instruction.Operand is Instruction operandInstruction) { - if (operandInstruction == oldTarget) + if (targetsMap.TryGetValue(operandInstruction.Offset, out Instruction newTarget)) { instruction.Operand = newTarget; - return; } } else if (instruction.Operand is Instruction[] operandInstructions) { for (int i = 0; i < operandInstructions.Length; i++) { - if (operandInstructions[i] == oldTarget) + if (targetsMap.TryGetValue(operandInstructions[i].Offset, out Instruction newTarget)) operandInstructions[i] = newTarget; } } } - private static void ReplaceExceptionHandlerBoundary(ExceptionHandler handler, Instruction oldTarget, Instruction newTarget) + private static void ReplaceExceptionHandlerBoundary(ExceptionHandler handler, IDictionary targetsMap) { - if (handler.FilterStart == oldTarget) - handler.FilterStart = newTarget; + if (handler.FilterStart is not null && targetsMap.TryGetValue(handler.FilterStart.Offset, out Instruction newFilterStart)) + handler.FilterStart = newFilterStart; - if (handler.HandlerEnd == oldTarget) - handler.HandlerEnd = newTarget; + if (handler.HandlerEnd is not null && targetsMap.TryGetValue(handler.HandlerEnd.Offset, out Instruction newHandlerEnd)) + handler.HandlerEnd = newHandlerEnd; - if (handler.HandlerStart == oldTarget) - handler.HandlerStart = newTarget; + if (handler.HandlerStart is not null && targetsMap.TryGetValue(handler.HandlerStart.Offset, out Instruction newHandlerStart)) + handler.HandlerStart = newHandlerStart; - if (handler.TryEnd == oldTarget) - handler.TryEnd = newTarget; + if (handler.TryEnd is not null && targetsMap.TryGetValue(handler.TryEnd.Offset, out Instruction newTryEnd)) + handler.TryEnd = newTryEnd; - if (handler.TryStart == oldTarget) - handler.TryStart = newTarget; + if (handler.TryStart is not null && targetsMap.TryGetValue(handler.TryStart.Offset, out Instruction newTryStart)) + handler.TryStart = newTryStart; } private bool IsExcludeAttribute(CustomAttribute customAttribute) From 32bcff149f1e0df7f3ff1a6d69676937f8f462fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Thu, 27 Oct 2022 09:54:43 +0200 Subject: [PATCH 15/16] TypeLoadException for certain combinations with Microsoft.Extensions.DependencyInjection 6.0.1 (#1395) --- Directory.Build.targets | 3 +-- Documentation/Changelog.md | 1 + src/coverlet.core/coverlet.core.csproj | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index f6cd1b61d..9438671ed 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -4,8 +4,7 @@ - - + diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index f61ee169b..73bd7cd11 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Fixed +-Fix TypeLoadException when referencing Microsoft.Extensions.DependencyInjection v6.0.1 [#1390](https://github.com/coverlet-coverage/coverlet/issues/1390) -Source Link for code generators fails [#1322](https://github.com/coverlet-coverage/coverlet/issues/1322) -Await foreach has wrong branch coverage when method is generic [#1210](https://github.com/coverlet-coverage/coverlet/issues/1210) -ExcludeFromCodeCoverage attribute on local functions ignores lambda expression [#1302](https://github.com/coverlet-coverage/coverlet/issues/1302) diff --git a/src/coverlet.core/coverlet.core.csproj b/src/coverlet.core/coverlet.core.csproj index 7ef394311..abcb31194 100644 --- a/src/coverlet.core/coverlet.core.csproj +++ b/src/coverlet.core/coverlet.core.csproj @@ -14,7 +14,6 @@ - From e2c9d84a84a9d2d240ac15feb70f9198c6f8e173 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sat, 29 Oct 2022 17:04:53 +0200 Subject: [PATCH 16/16] Prepare release (#1400) --- src/coverlet.core/coverlet.core.csproj | 2 +- version.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coverlet.core/coverlet.core.csproj b/src/coverlet.core/coverlet.core.csproj index abcb31194..cb484014d 100644 --- a/src/coverlet.core/coverlet.core.csproj +++ b/src/coverlet.core/coverlet.core.csproj @@ -3,7 +3,7 @@ Library netstandard2.0 - 5.7.2 + 5.8.0 false diff --git a/version.json b/version.json index 8db7c19a6..306edac91 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "3.1.3-preview.{height}", + "version": "3.2.0", "publicReleaseRefSpec": [ "^refs/heads/master$" ],