From 77a68d9dbb63eb77caa58f5924e35b3b4d5c421e Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Fri, 25 Aug 2023 13:08:29 +0200 Subject: [PATCH 1/2] apply code style rules + update headers --- .editorconfig | 400 ++++++++++++++++++ MSBuildLocator.sln | 1 + samples/BuilderApp/Program.cs | 45 +- .../QueryInstanceTests.cs | 4 +- src/MSBuildLocator.Tests/QueryOptionsTests.cs | 8 +- .../SemanticVersionParserTests.cs | 63 +-- src/MSBuildLocator/DiscoveryType.cs | 6 +- src/MSBuildLocator/DotNetSdkLocationHelper.cs | 99 ++--- src/MSBuildLocator/MSBuildLocator.cs | 94 ++-- src/MSBuildLocator/NativeMethods.cs | 4 +- src/MSBuildLocator/Properties/AssemblyInfo.cs | 6 +- src/MSBuildLocator/Utils/SemanticVersion.cs | 25 +- .../Utils/SemanticVersionParser.cs | 9 +- src/MSBuildLocator/Utils/VersionComparer.cs | 30 +- src/MSBuildLocator/VisualStudioInstance.cs | 6 +- .../VisualStudioInstanceQueryOptions.cs | 4 +- .../VisualStudioLocationHelper.cs | 30 +- 17 files changed, 606 insertions(+), 228 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..69a8cdc0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,400 @@ +# editorconfig.org + +# top-most EditorConfig file +root = true + +# Default settings: +# A newline ending every file +# Use 4 spaces as indentation +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[project.json] +indent_size = 2 + +# C# files +[*.cs] +# 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 + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# Types: use keywords instead of BCL types, and permit var only when the type is clear +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:none +csharp_style_var_elsewhere = false:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# 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 + +# Code style defaults +csharp_using_directive_placement = outside_namespace:suggestion +dotnet_sort_system_directives_first = true +csharp_prefer_braces = true:silent +csharp_preserve_single_line_blocks = true:none +csharp_preserve_single_line_statements = false:none +csharp_prefer_static_local_function = true:suggestion +csharp_prefer_simple_using_statement = false:none +csharp_style_prefer_switch_expression = true:suggestion + +# Code quality +dotnet_style_readonly_field = true:suggestion +dotnet_code_quality_unused_parameters = non_public:suggestion + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +csharp_prefer_simple_default_expression = true:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_constructors = true:silent +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = true:silent + +# Pattern matching +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Other features +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_pattern_local_over_anonymous_function = false:none + +# 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 + +# Analyzers +dotnet_code_quality.ca1802.api_surface = private, internal +dotnet_code_quality.ca2208.api_surface = public + +# CA1852: Seal internal types +dotnet_diagnostic.ca1852.severity = warning + +# RS0037: Enable tracking of nullability of reference types in the declared API +# Our API is not annotated but new classes get nullable enabled so disable this. +# We'd be happy if everything was annotated and this could be removed. +dotnet_diagnostic.RS0037.severity = none + +# License header +file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license. + +# C++ Files +[*.{cpp,h,in}] +curly_bracket_next_line = true +indent_brace_style = Allman + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +[*.{csproj,vbproj,proj,nativeproj,locproj}] +charset = utf-8 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# YAML config files +[*.{yml,yaml}] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf +[*.{cmd, bat}] +end_of_line = crlf + +[src/**/*.{cs,vb}] +# Code style checks +dotnet_analyzer_diagnostic.category-Style.severity = warning + +# Cast is redundant +dotnet_diagnostic.IDE0004.severity = suggestion + +# IDE0005: Remove unnecessary usings/imports +dotnet_diagnostic.IDE0005.severity = none + +# Use explicit type instead of 'var' +dotnet_diagnostic.IDE0008.severity = suggestion + +# Populate switch +dotnet_diagnostic.IDE0010.severity = suggestion + +# Null check can be simplified +dotnet_diagnostic.IDE0016.severity = suggestion + +# Object initialization can be simplified +dotnet_diagnostic.IDE0017.severity = suggestion + +# Variable declaration can be inlined +dotnet_diagnostic.IDE0018.severity = suggestion + +# Use pattern matching +dotnet_diagnostic.IDE0019.severity = suggestion +dotnet_diagnostic.IDE0020.severity = suggestion + +# Use expression body for constructor +dotnet_diagnostic.IDE0021.severity = suggestion + +# Use expression body for method +dotnet_diagnostic.IDE0022.severity = suggestion + +# Use expression body for conversion operator +dotnet_diagnostic.IDE0023.severity = suggestion + +# Use block body for operator +dotnet_diagnostic.IDE0024.severity = suggestion + +# Use expression body for property +dotnet_diagnostic.IDE0025.severity = suggestion + +# Use expression body for indexer +dotnet_diagnostic.IDE0026.severity = suggestion + +# Use expression body for accessor +dotnet_diagnostic.IDE0027.severity = suggestion + +# Collection initialization can be simplified +dotnet_diagnostic.IDE0028.severity = suggestion + +# Null check can be simplified +dotnet_diagnostic.IDE0031.severity = suggestion + +# Use auto property +dotnet_diagnostic.IDE0032.severity = suggestion + +# 'default' expression can be simplified +dotnet_diagnostic.IDE0034.severity = suggestion + +# Member name can be simplified +dotnet_diagnostic.IDE0037.severity = suggestion + +# Use local function +dotnet_diagnostic.IDE0039.severity = suggestion + +# Null check can be simplified +dotnet_diagnostic.IDE0041.severity = suggestion + +# Variable declaration can be deconstructed +dotnet_diagnostic.IDE0042.severity = suggestion + +# Made field readonly +dotnet_diagnostic.IDE0044.severity = suggestion + +# 'if' statement can be simplified +dotnet_diagnostic.IDE0045.severity = suggestion +dotnet_diagnostic.IDE0046.severity = suggestion + +# Parentheses can be removed +dotnet_diagnostic.IDE0047.severity = suggestion + +# Parentheses should be added for clarity +dotnet_diagnostic.IDE0048.severity = suggestion + +# Member name can be simplified +dotnet_diagnostic.IDE0049.severity = suggestion + +# Use compound assignment +dotnet_diagnostic.IDE0054.severity = suggestion + +# Fix formatting +dotnet_diagnostic.IDE0055.severity = suggestion + +# Indexing can be simplified +dotnet_diagnostic.IDE0056.severity = suggestion + +# Slice can be simplified +dotnet_diagnostic.IDE0057.severity = suggestion + +# Expression value is never used +dotnet_diagnostic.IDE0058.severity = suggestion + +# Unnecessary assignment of a value +dotnet_diagnostic.IDE0059.severity = suggestion + +# Remove unused parameter +dotnet_diagnostic.IDE0060.severity = suggestion + +# Use expression body for a local function +dotnet_diagnostic.IDE0061.severity = suggestion + +# Local function can be made static +dotnet_diagnostic.IDE0062.severity = suggestion + +# Using directives must be placed outside of a namespace declaration +dotnet_diagnostic.IDE0065.severity = suggestion + +# Use 'switch' expression +dotnet_diagnostic.IDE0066.severity = suggestion + +# 'GetHashCode' implementation can be simplified +dotnet_diagnostic.IDE0070.severity = suggestion + +# Interpolation can be simplified +dotnet_diagnostic.IDE0071.severity = suggestion + +# Populate switch +dotnet_diagnostic.IDE0072.severity = suggestion + +# Use compound assignment +dotnet_diagnostic.IDE0074.severity = suggestion + +# Conditional expression can be simplified +dotnet_diagnostic.IDE0075.severity = suggestion + +# Use pattern matching +dotnet_diagnostic.IDE0078.severity = suggestion +dotnet_diagnostic.IDE0083.severity = suggestion + +# 'typeof' can be converted to 'nameof' +dotnet_diagnostic.IDE0082.severity = suggestion + +# 'new' expression can be simplified +dotnet_diagnostic.IDE0090.severity = suggestion + +# Simplify LINQ expression +dotnet_diagnostic.IDE0120.severity = suggestion + +# namespace does not match folder structure +dotnet_diagnostic.IDE0130.severity = suggestion + +# Null check can be clarified +dotnet_diagnostic.IDE0150.severity = suggestion + +# Convert to block scoped namespaces +dotnet_diagnostic.IDE0160.severity = suggestion + +# Simplify property pattern +dotnet_diagnostic.IDE0170.severity = suggestion + +# Use tuple to swap values +dotnet_diagnostic.IDE0180.severity = suggestion + +# Use tuple to swap values +dotnet_diagnostic.IDE0180.severity = suggestion + +# Lambda expression can be removed +dotnet_diagnostic.IDE0200.severity = suggestion + +# Convert to top-level statements +dotnet_diagnostic.IDE0210.severity = suggestion + +# 'foreach' statement implicitly converts +dotnet_diagnostic.IDE0220.severity = suggestion + +# Use UTF-8 string literal +dotnet_diagnostic.IDE0230.severity = suggestion + +# Nullable directives +dotnet_diagnostic.IDE0240.severity = suggestion +dotnet_diagnostic.IDE0241.severity = suggestion + +# Struct can be made 'readonly' +dotnet_diagnostic.IDE0250.severity = suggestion + +# Struct methods can be made 'readonly' +dotnet_diagnostic.IDE0251.severity = suggestion + +# Null check can be simplified +dotnet_diagnostic.IDE0270.severity = suggestion + +# naming rule violation +dotnet_diagnostic.IDE1006.severity = suggestion diff --git a/MSBuildLocator.sln b/MSBuildLocator.sln index 4540e62d..68f161de 100644 --- a/MSBuildLocator.sln +++ b/MSBuildLocator.sln @@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props version.json = version.json + .editorconfig = .editorconfig EndProjectSection EndProject Global diff --git a/samples/BuilderApp/Program.cs b/samples/BuilderApp/Program.cs index 0ec2f0bc..56d8ccc4 100644 --- a/samples/BuilderApp/Program.cs +++ b/samples/BuilderApp/Program.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection; using Microsoft.Build.Construction; using Microsoft.Build.Evaluation; using Microsoft.Build.Framework; @@ -13,37 +14,37 @@ namespace BuilderApp { - internal class Program + internal sealed class Program { private static void Main(string[] args) { Header(); - var projectFilePath = Args(args); + string projectFilePath = Args(args); // Before we can build we need to resolve MSBuild assemblies. We could: // 1) Use defaults and call: MSBuildLocator.RegisterDefaults(); // 2) Do something fancier and ask the user. As an example we'll do that. var instances = MSBuildLocator.QueryVisualStudioInstances().ToList(); - var msbuildDeploymentToUse = AskWhichMSBuildToUse(instances); + (VisualStudioInstance VSInstance, string MSBuildPath) = AskWhichMSBuildToUse(instances); // Calling Register methods will subscribe to AssemblyResolve event. After this we can // safely call code that use MSBuild types (in the Builder class). - if (msbuildDeploymentToUse.VSInstance != null) + if (VSInstance != null) { - Console.WriteLine($"Using MSBuild from VS Instance: {msbuildDeploymentToUse.VSInstance.Name} - {msbuildDeploymentToUse.VSInstance.Version}"); + Console.WriteLine($"Using MSBuild from VS Instance: {VSInstance.Name} - {VSInstance.Version}"); Console.WriteLine(); - MSBuildLocator.RegisterInstance(msbuildDeploymentToUse.VSInstance); + MSBuildLocator.RegisterInstance(VSInstance); } else { - Console.WriteLine($"Using MSBuild from path: {msbuildDeploymentToUse.MSBuildPath}"); + Console.WriteLine($"Using MSBuild from path: {MSBuildPath}"); Console.WriteLine(); - MSBuildLocator.RegisterMSBuildPath(msbuildDeploymentToUse.MSBuildPath); + MSBuildLocator.RegisterMSBuildPath(MSBuildPath); } - var result = new Builder().Build(projectFilePath); + bool result = Builder.Build(projectFilePath); Console.WriteLine(); Console.ForegroundColor = result ? ConsoleColor.Green : ConsoleColor.Red; @@ -59,10 +60,10 @@ private static (VisualStudioInstance VSInstance, string MSBuildPath) AskWhichMSB } Console.WriteLine($"0) Custom path"); - for (var i = 1; i <= instances.Count; i++) + for (int i = 1; i <= instances.Count; i++) { - var instance = instances[i - 1]; - var recommended = string.Empty; + VisualStudioInstance instance = instances[i - 1]; + string recommended = string.Empty; // The dev console is probably always the right choice because the user explicitly opened // one associated with a Visual Studio install. It will always be first in the list. @@ -74,27 +75,27 @@ private static (VisualStudioInstance VSInstance, string MSBuildPath) AskWhichMSB Console.WriteLine(); Console.WriteLine("Select an instance of MSBuild: "); - var answer = Console.ReadLine(); + string answer = Console.ReadLine(); if (int.TryParse(answer, out int instanceChoice) && instanceChoice >= 0 && instanceChoice <= instances.Count) { if (instanceChoice == 0) { Console.WriteLine("Input path to MSBuild deployment:"); - var msbuildPath = Console.ReadLine(); + string msBuildPath = Console.ReadLine(); - if (!Directory.Exists(msbuildPath)) + if (!Directory.Exists(msBuildPath)) { - Console.WriteLine($"Directory does not exist: {msbuildPath}"); + Console.WriteLine($"Directory does not exist: {msBuildPath}"); Environment.Exit(-1); } - return (null, msbuildPath); + return (null, msBuildPath); } else { - var instanceUsed = instances[instanceChoice - 1]; + VisualStudioInstance instanceUsed = instances[instanceChoice - 1]; return (instanceUsed, null); } } @@ -116,7 +117,7 @@ private static void Header() private static string Args(string[] args) { if (args.Length < 1 || !File.Exists(args[0])) Usage(); - var projectFilePath = args[0]; + string projectFilePath = args[0]; return projectFilePath; } @@ -139,9 +140,9 @@ private static void Usage() /// public class Builder { - public bool Build(string projectFile) + public static bool Build(string projectFile) { - var assembly = typeof(Project).Assembly; + Assembly assembly = typeof(Project).Assembly; FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); Console.WriteLine(); @@ -154,7 +155,7 @@ public bool Build(string projectFile) return project.Build(new Logger()); } - private class Logger : ILogger + private sealed class Logger : ILogger { public void Initialize(IEventSource eventSource) { diff --git a/src/MSBuildLocator.Tests/QueryInstanceTests.cs b/src/MSBuildLocator.Tests/QueryInstanceTests.cs index a98b3ab6..9f1897b0 100644 --- a/src/MSBuildLocator.Tests/QueryInstanceTests.cs +++ b/src/MSBuildLocator.Tests/QueryInstanceTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using Shouldly; using System.Linq; diff --git a/src/MSBuildLocator.Tests/QueryOptionsTests.cs b/src/MSBuildLocator.Tests/QueryOptionsTests.cs index c9fb62ea..28b7568f 100644 --- a/src/MSBuildLocator.Tests/QueryOptionsTests.cs +++ b/src/MSBuildLocator.Tests/QueryOptionsTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using Shouldly; using System; @@ -55,7 +55,7 @@ public void NoResultsTest() VerifyQueryResults(instances, DiscoveryType.DotNetSdk); } - private void VerifyQueryResults(IEnumerable instances, DiscoveryType discoveryTypes, params string[] expectedInstanceNames) + private static void VerifyQueryResults(IEnumerable instances, DiscoveryType discoveryTypes, params string[] expectedInstanceNames) { IEnumerable actual = MSBuildLocator.QueryVisualStudioInstances(instances, new VisualStudioInstanceQueryOptions { @@ -76,4 +76,4 @@ private void VerifyQueryResults(IEnumerable instances, Dis } } } -} \ No newline at end of file +} diff --git a/src/MSBuildLocator.Tests/SemanticVersionParserTests.cs b/src/MSBuildLocator.Tests/SemanticVersionParserTests.cs index f9e57b3f..03c9b8d2 100644 --- a/src/MSBuildLocator.Tests/SemanticVersionParserTests.cs +++ b/src/MSBuildLocator.Tests/SemanticVersionParserTests.cs @@ -1,8 +1,9 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. #if NETCOREAPP +using Microsoft.Build.Locator.Utils; using Shouldly; using System.Linq; using Xunit; @@ -14,61 +15,61 @@ public class SemanticVersionParserTests [Fact] public void TryParseTest_ReleaseVersion() { - var version = "7.0.333"; + string version = "7.0.333"; - var isParsed = SemanticVersionParser.TryParse(version, out var parsedVerion); + bool isParsed = SemanticVersionParser.TryParse(version, out SemanticVersion parsedVersion); - parsedVerion.ShouldNotBeNull(); + _ = parsedVersion.ShouldNotBeNull(); isParsed.ShouldBeTrue(); - parsedVerion.Major.ShouldBe(7); - parsedVerion.Minor.ShouldBe(0); - parsedVerion.Patch.ShouldBe(333); - parsedVerion.ReleaseLabels.ShouldBeEmpty(); + parsedVersion.Major.ShouldBe(7); + parsedVersion.Minor.ShouldBe(0); + parsedVersion.Patch.ShouldBe(333); + parsedVersion.ReleaseLabels.ShouldBeEmpty(); } [Fact] public void TryParseTest_PreviewVersion() { - var version = "8.0.0-preview.6.23329.7"; + string version = "8.0.0-preview.6.23329.7"; - var isParsed = SemanticVersionParser.TryParse(version, out var parsedVerion); + bool isParsed = SemanticVersionParser.TryParse(version, out SemanticVersion parsedVersion); - parsedVerion.ShouldNotBeNull(); + _ = parsedVersion.ShouldNotBeNull(); isParsed.ShouldBeTrue(); - parsedVerion.Major.ShouldBe(8); - parsedVerion.Minor.ShouldBe(0); - parsedVerion.Patch.ShouldBe(0); - parsedVerion.ReleaseLabels.ShouldBe(new[] { "preview", "6", "23329", "7" }); + parsedVersion.Major.ShouldBe(8); + parsedVersion.Minor.ShouldBe(0); + parsedVersion.Patch.ShouldBe(0); + parsedVersion.ReleaseLabels.ShouldBe(new[] { "preview", "6", "23329", "7" }); } [Fact] public void TryParseTest_InvalidInput_LeadingZero() { - var version = "0.0-preview.6"; + string version = "0.0-preview.6"; - var isParsed = SemanticVersionParser.TryParse(version, out var parsedVerion); + bool isParsed = SemanticVersionParser.TryParse(version, out SemanticVersion parsedVersion); - Assert.Null(parsedVerion); + Assert.Null(parsedVersion); isParsed.ShouldBeFalse(); } [Fact] public void TryParseTest_InvalidInput_FourPartsVersion() { - var version = "5.0.3.4"; + string version = "5.0.3.4"; - var isParsed = SemanticVersionParser.TryParse(version, out var parsedVerion); + bool isParsed = SemanticVersionParser.TryParse(version, out SemanticVersion parsedVersion); - Assert.Null(parsedVerion); + Assert.Null(parsedVersion); isParsed.ShouldBeFalse(); } [Fact] public void VersionSortingTest_WithPreview() { - var versions = new[] { "7.0.7", "8.0.0-preview.6.23329.7", "8.0.0-preview.3.23174.8" }; + string[] versions = new[] { "7.0.7", "8.0.0-preview.6.23329.7", "8.0.0-preview.3.23174.8" }; - var maxVersion = versions.Select(v => SemanticVersionParser.TryParse(v, out var parsedVerion) ? parsedVerion : null).Max(); + SemanticVersion maxVersion = versions.Select(v => SemanticVersionParser.TryParse(v, out SemanticVersion parsedVersion) ? parsedVersion : null).Max(); maxVersion.OriginalValue.ShouldBe("8.0.0-preview.6.23329.7"); } @@ -76,9 +77,9 @@ public void VersionSortingTest_WithPreview() [Fact] public void VersionSortingTest_ReleaseOnly() { - var versions = new[] { "7.0.7", "3.7.2", "10.0.0" }; + string[] versions = new[] { "7.0.7", "3.7.2", "10.0.0" }; - var maxVersion = versions.Max(v => SemanticVersionParser.TryParse(v, out var parsedVerion) ? parsedVerion : null); + SemanticVersion maxVersion = versions.Max(v => SemanticVersionParser.TryParse(v, out SemanticVersion parsedVersion) ? parsedVersion : null); maxVersion.OriginalValue.ShouldBe("10.0.0"); } @@ -86,9 +87,9 @@ public void VersionSortingTest_ReleaseOnly() [Fact] public void VersionSortingTest_WithInvalidFolderNames() { - var versions = new[] { "7.0.7", "3.7.2", "dummy", "5.7.8.9" }; + string[] versions = new[] { "7.0.7", "3.7.2", "dummy", "5.7.8.9" }; - var maxVersion = versions.Max(v => SemanticVersionParser.TryParse(v, out var parsedVerion) ? parsedVerion : null); + SemanticVersion maxVersion = versions.Max(v => SemanticVersionParser.TryParse(v, out SemanticVersion parsedVersion) ? parsedVersion : null); maxVersion.OriginalValue.ShouldBe("7.0.7"); } @@ -96,12 +97,12 @@ public void VersionSortingTest_WithInvalidFolderNames() [Fact] public void VersionSortingTest_WithAllInvalidFolderNames() { - var versions = new[] { "dummy", "5.7.8.9" }; + string[] versions = new[] { "dummy", "5.7.8.9" }; - var maxVersion = versions.Max(v => SemanticVersionParser.TryParse(v, out var parsedVerion) ? parsedVerion : null); + SemanticVersion maxVersion = versions.Max(v => SemanticVersionParser.TryParse(v, out SemanticVersion parsedVersion) ? parsedVersion : null); maxVersion.ShouldBeNull(); } } } -#endif \ No newline at end of file +#endif diff --git a/src/MSBuildLocator/DiscoveryType.cs b/src/MSBuildLocator/DiscoveryType.cs index 7a4ad585..f5e39920 100644 --- a/src/MSBuildLocator/DiscoveryType.cs +++ b/src/MSBuildLocator/DiscoveryType.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; @@ -27,4 +27,4 @@ public enum DiscoveryType /// DotNetSdk = 4 } -} \ No newline at end of file +} diff --git a/src/MSBuildLocator/DotNetSdkLocationHelper.cs b/src/MSBuildLocator/DotNetSdkLocationHelper.cs index fab49876..176b21f6 100644 --- a/src/MSBuildLocator/DotNetSdkLocationHelper.cs +++ b/src/MSBuildLocator/DotNetSdkLocationHelper.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. #if NETCOREAPP @@ -11,6 +11,7 @@ using System.Runtime.InteropServices; using System.Runtime.Loader; using System.Text.RegularExpressions; +using Microsoft.Build.Locator.Utils; #nullable enable @@ -18,10 +19,10 @@ namespace Microsoft.Build.Locator { internal static class DotNetSdkLocationHelper { - private static readonly Regex VersionRegex = new Regex(@"^(\d+)\.(\d+)\.(\d+)", RegexOptions.Multiline); - private static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - private static readonly string ExeName = IsWindows ? "dotnet.exe" : "dotnet"; - private static readonly Lazy DotnetPath = new(() => ResolveDotnetPath()); + private static readonly Regex s_versionRegex = new(@"^(\d+)\.(\d+)\.(\d+)", RegexOptions.Multiline); + private static readonly bool s_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + private static readonly string s_exeName = s_isWindows ? "dotnet.exe" : "dotnet"; + private static readonly Lazy s_dotnetPath = new(() => ResolveDotnetPath()); public static VisualStudioInstance? GetInstance(string dotNetSdkPath) { @@ -37,7 +38,7 @@ internal static class DotNetSdkLocationHelper } // Preview versions contain a hyphen after the numeric part of the version. Version.TryParse doesn't accept that. - Match versionMatch = VersionRegex.Match(File.ReadAllText(versionPath)); + Match versionMatch = s_versionRegex.Match(File.ReadAllText(versionPath)); if (!versionMatch.Success) { @@ -69,10 +70,10 @@ internal static class DotNetSdkLocationHelper } public static IEnumerable GetInstances(string workingDirectory) - { - foreach (var basePath in GetDotNetBasePaths(workingDirectory)) + { + foreach (string basePath in GetDotNetBasePaths(workingDirectory)) { - var dotnetSdk = GetInstance(basePath); + VisualStudioInstance? dotnetSdk = GetInstance(basePath); if (dotnetSdk != null) { yield return dotnetSdk; @@ -118,7 +119,7 @@ private static IEnumerable GetDotNetBasePaths(string workingDirectory) private static void ModifyUnmanagedDllResolver(Action resolverAction) { // For Windows hostfxr is loaded in the process. - if (!IsWindows) + if (!s_isWindows) { var loadContext = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); if (loadContext != null) @@ -130,28 +131,28 @@ private static void ModifyUnmanagedDllResolver(Action resol private static IntPtr HostFxrResolver(Assembly assembly, string libraryName) { - var hostFxrLibName = "libhostfxr"; - var libExtension = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "dylib" : "so"; + string hostFxrLibName = "libhostfxr"; + string libExtension = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "dylib" : "so"; if (!hostFxrLibName.Equals(libraryName)) { return IntPtr.Zero; } - var hostFxrRoot = Path.Combine(DotnetPath.Value, "host", "fxr"); + string hostFxrRoot = Path.Combine(s_dotnetPath.Value, "host", "fxr"); if (Directory.Exists(hostFxrRoot)) { // Load hostfxr from the highest version, because it should be backward-compatible - var hostFxrAssemblyDirectory = Directory.GetDirectories(hostFxrRoot) - .Max(str => SemanticVersionParser.TryParse(str, out var version) ? version : null); + SemanticVersion? hostFxrAssemblyDirectory = Directory.GetDirectories(hostFxrRoot) + .Max(str => SemanticVersionParser.TryParse(str, out SemanticVersion? version) ? version : null); if (hostFxrAssemblyDirectory != null && !string.IsNullOrEmpty(hostFxrAssemblyDirectory.OriginalValue)) { - var hostFxrAssembly = Path.Combine(hostFxrAssemblyDirectory.OriginalValue, Path.ChangeExtension(hostFxrLibName, libExtension)); + string hostFxrAssembly = Path.Combine(hostFxrAssemblyDirectory.OriginalValue, Path.ChangeExtension(hostFxrLibName, libExtension)); if (File.Exists(hostFxrAssembly)) { - return NativeLibrary.TryLoad(hostFxrAssembly, out var handle) ? handle : IntPtr.Zero; + return NativeLibrary.TryLoad(hostFxrAssembly, out IntPtr handle) ? handle : IntPtr.Zero; } } } @@ -160,7 +161,7 @@ private static IntPtr HostFxrResolver(Assembly assembly, string libraryName) } private static string SdkResolutionExceptionMessage(string methodName) => $"Failed to find all versions of .NET Core MSBuild. Call to {methodName}. There may be more details in stderr."; - + /// /// Determines the directory location of the SDK accounting for /// global.json and multi-level lookup policy. @@ -168,7 +169,7 @@ private static IntPtr HostFxrResolver(Assembly assembly, string libraryName) private static string? GetSdkFromGlobalSettings(string workingDirectory) { string? resolvedSdk = null; - int rc = NativeMethods.hostfxr_resolve_sdk2(exe_dir: DotnetPath.Value, working_dir: workingDirectory, flags: 0, result: (key, value) => + int rc = NativeMethods.hostfxr_resolve_sdk2(exe_dir: s_dotnetPath.Value, working_dir: workingDirectory, flags: 0, result: (key, value) => { if (key == NativeMethods.hostfxr_resolve_sdk2_result_key_t.resolved_sdk_dir) { @@ -176,12 +177,9 @@ private static IntPtr HostFxrResolver(Assembly assembly, string libraryName) } }); - if (rc != 0) - { - throw new InvalidOperationException(SdkResolutionExceptionMessage(nameof(NativeMethods.hostfxr_resolve_sdk2))); - } - - return resolvedSdk; + return rc != 0 + ? throw new InvalidOperationException(SdkResolutionExceptionMessage(nameof(NativeMethods.hostfxr_resolve_sdk2))) + : resolvedSdk; } private static string ResolveDotnetPath() @@ -191,35 +189,27 @@ private static string ResolveDotnetPath() if (string.IsNullOrEmpty(dotnetPath)) { string? dotnetExePath = GetCurrentProcessPath(); - var isRunFromDotnetExecutable = !string.IsNullOrEmpty(dotnetExePath) - && Path.GetFileName(dotnetExePath).Equals(ExeName, StringComparison.InvariantCultureIgnoreCase); - - if (isRunFromDotnetExecutable) - { - dotnetPath = Path.GetDirectoryName(dotnetExePath); - } - else - { - dotnetPath = FindDotnetPathFromEnvVariable("DOTNET_HOST_PATH") + bool isRunFromDotnetExecutable = !string.IsNullOrEmpty(dotnetExePath) + && Path.GetFileName(dotnetExePath).Equals(s_exeName, StringComparison.InvariantCultureIgnoreCase); + + dotnetPath = isRunFromDotnetExecutable + ? Path.GetDirectoryName(dotnetExePath) + : FindDotnetPathFromEnvVariable("DOTNET_HOST_PATH") ?? FindDotnetPathFromEnvVariable("DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR") ?? GetDotnetPathFromPATH(); - } } - if (string.IsNullOrEmpty(dotnetPath)) - { - throw new InvalidOperationException("Could not find the dotnet executable. Is it set on the DOTNET_ROOT?"); - } - - return dotnetPath; + return string.IsNullOrEmpty(dotnetPath) + ? throw new InvalidOperationException("Could not find the dotnet executable. Is it set on the DOTNET_ROOT?") + : dotnetPath; } private static string? GetDotnetPathFromROOT() { // 32-bit architecture has (x86) suffix string envVarName = (IntPtr.Size == 4) ? "DOTNET_ROOT(x86)" : "DOTNET_ROOT"; - var dotnetPath = FindDotnetPathFromEnvVariable(envVarName); - + string? dotnetPath = FindDotnetPathFromEnvVariable(envVarName); + return dotnetPath; } @@ -234,7 +224,7 @@ private static string ResolveDotnetPath() // https://github.com/dotnet/designs/blob/main/accepted/2021/install-location-per-architecture.md // This could be done using the nethost library, but this is currently shipped as metadata package (Microsoft.NETCore.DotNetAppHost) and requires the customers // to specify for resolving runtime assembly. - var paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator) ?? Array.Empty(); + string[] paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator) ?? Array.Empty(); foreach (string dir in paths) { string? filePath = ValidatePath(dir); @@ -254,15 +244,12 @@ private static string ResolveDotnetPath() private static string[] GetAllAvailableSDKs() { string[]? resolvedPaths = null; - int rc = NativeMethods.hostfxr_get_available_sdks(exe_dir: DotnetPath.Value, result: (key, value) => resolvedPaths = value); + int rc = NativeMethods.hostfxr_get_available_sdks(exe_dir: s_dotnetPath.Value, result: (key, value) => resolvedPaths = value); // Errors are automatically printed to stderr. We should not continue to try to output anything if we failed. - if (rc != 0) - { - throw new InvalidOperationException(SdkResolutionExceptionMessage(nameof(NativeMethods.hostfxr_get_available_sdks))); - } - - return resolvedPaths ?? Array.Empty(); + return rc != 0 + ? throw new InvalidOperationException(SdkResolutionExceptionMessage(nameof(NativeMethods.hostfxr_get_available_sdks))) + : resolvedPaths ?? Array.Empty(); } /// @@ -281,16 +268,16 @@ private static string[] GetAllAvailableSDKs() private static string? FindDotnetPathFromEnvVariable(string environmentVariable) { string? dotnetPath = Environment.GetEnvironmentVariable(environmentVariable); - + return string.IsNullOrEmpty(dotnetPath) ? null : ValidatePath(dotnetPath); } private static string? ValidatePath(string dotnetPath) { - string fullPathToDotnetFromRoot = Path.Combine(dotnetPath, ExeName); + string fullPathToDotnetFromRoot = Path.Combine(dotnetPath, s_exeName); if (File.Exists(fullPathToDotnetFromRoot)) { - if (!IsWindows) + if (!s_isWindows) { fullPathToDotnetFromRoot = realpath(fullPathToDotnetFromRoot) ?? fullPathToDotnetFromRoot; return File.Exists(fullPathToDotnetFromRoot) ? Path.GetDirectoryName(fullPathToDotnetFromRoot) : null; diff --git a/src/MSBuildLocator/MSBuildLocator.cs b/src/MSBuildLocator/MSBuildLocator.cs index ab435c86..0d6920be 100644 --- a/src/MSBuildLocator/MSBuildLocator.cs +++ b/src/MSBuildLocator/MSBuildLocator.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; @@ -60,10 +60,7 @@ public static class MSBuildLocator /// Only includes Visual Studio 2017 (v15.0) and higher. /// /// Enumeration of all Visual Studio instances detected on the machine. - public static IEnumerable QueryVisualStudioInstances() - { - return QueryVisualStudioInstances(VisualStudioInstanceQueryOptions.Default); - } + public static IEnumerable QueryVisualStudioInstances() => QueryVisualStudioInstances(VisualStudioInstanceQueryOptions.Default); /// /// Query for Visual Studio instances matching the given options. @@ -74,17 +71,11 @@ public static IEnumerable QueryVisualStudioInstances() /// Query options for Visual Studio instances. /// Enumeration of Visual Studio instances detected on the machine. public static IEnumerable QueryVisualStudioInstances( - VisualStudioInstanceQueryOptions options) - { - return QueryVisualStudioInstances(GetInstances(options), options); - } + VisualStudioInstanceQueryOptions options) => QueryVisualStudioInstances(GetInstances(options), options); internal static IEnumerable QueryVisualStudioInstances( IEnumerable instances, - VisualStudioInstanceQueryOptions options) - { - return instances.Where(i => options.DiscoveryTypes.HasFlag(i.DiscoveryType)); - } + VisualStudioInstanceQueryOptions options) => instances.Where(i => options.DiscoveryTypes.HasFlag(i.DiscoveryType)); /// /// Discover instances of Visual Studio and register the first one. See . @@ -95,7 +86,7 @@ public static VisualStudioInstance RegisterDefaults() VisualStudioInstance instance = GetInstances(VisualStudioInstanceQueryOptions.Default).FirstOrDefault(); if (instance == null) { - var error = "No instances of MSBuild could be detected." + + string error = "No instances of MSBuild could be detected." + Environment.NewLine + $"Try calling {nameof(RegisterInstance)} or {nameof(RegisterMSBuildPath)} to manually register one."; @@ -143,17 +134,14 @@ public static void RegisterInstance(VisualStudioInstance instance) /// Add assembly resolution for Microsoft.Build core dlls in the current AppDomain from the specified /// path. /// - /// + /// /// Path to the directory containing a deployment of MSBuild binaries. /// A minimal MSBuild deployment would be the publish result of the Microsoft.Build.Runtime package. /// /// In order to restore and build real projects, one needs a deployment that contains the rest of the toolchain (nuget, compilers, etc.). /// Such deployments can be found in installations such as Visual Studio or dotnet CLI. /// - public static void RegisterMSBuildPath(string msbuildPath) - { - RegisterMSBuildPath(new string[] { msbuildPath }); - } + public static void RegisterMSBuildPath(string msBuildPath) => RegisterMSBuildPath(new string[] { msBuildPath }); /// /// Add assembly resolution for Microsoft.Build core dlls in the current AppDomain from the specified @@ -178,7 +166,7 @@ public static void RegisterMSBuildPath(string[] msbuildSearchPaths) { if (string.IsNullOrWhiteSpace(msbuildSearchPaths[i])) { - nullOrWhiteSpaceExceptions.Add(new ArgumentException($"Value at position {i+1} may not be null or whitespace", nameof(msbuildSearchPaths))); + nullOrWhiteSpaceExceptions.Add(new ArgumentException($"Value at position {i + 1} may not be null or whitespace", nameof(msbuildSearchPaths))); } } if (nullOrWhiteSpaceExceptions.Count > 0) @@ -194,9 +182,9 @@ public static void RegisterMSBuildPath(string[] msbuildSearchPaths) if (!CanRegister) { - var loadedAssemblyList = string.Join(Environment.NewLine, LoadedMsBuildAssemblies.Select(a => a.GetName())); + string loadedAssemblyList = string.Join(Environment.NewLine, LoadedMsBuildAssemblies.Select(a => a.GetName())); - var error = $"{typeof(MSBuildLocator)}.{nameof(RegisterInstance)} was called, but MSBuild assemblies were already loaded." + + string error = $"{typeof(MSBuildLocator)}.{nameof(RegisterInstance)} was called, but MSBuild assemblies were already loaded." + Environment.NewLine + $"Ensure that {nameof(RegisterInstance)} is called before any method that directly references types in the Microsoft.Build namespace has been called." + Environment.NewLine + @@ -218,17 +206,17 @@ public static void RegisterMSBuildPath(string[] msbuildSearchPaths) // This overrides the latter assumption to let it find the right MSBuild. foreach (string path in msbuildSearchPaths) { - string msbuildExe = Path.Combine(path, "MSBuild.exe"); - if (File.Exists(msbuildExe)) + string msBuildExe = Path.Combine(path, "MSBuild.exe"); + if (File.Exists(msBuildExe)) { - FileVersionInfo ver = FileVersionInfo.GetVersionInfo(msbuildExe); + FileVersionInfo ver = FileVersionInfo.GetVersionInfo(msBuildExe); if (ver.FileMajorPart < 17 || (ver.FileMajorPart == 17 && ver.FileMinorPart < 1)) { - if (Path.GetDirectoryName(msbuildExe).EndsWith(@"\amd64", StringComparison.OrdinalIgnoreCase)) + if (Path.GetDirectoryName(msBuildExe).EndsWith(@"\amd64", StringComparison.OrdinalIgnoreCase)) { - msbuildExe = Path.Combine(path.Substring(0, path.Length - 6), "MSBuild.exe"); + msBuildExe = Path.Combine(path.Substring(0, path.Length - 6), "MSBuild.exe"); } - Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", msbuildExe); + Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", msBuildExe); } break; } @@ -245,10 +233,7 @@ public static void RegisterMSBuildPath(string[] msbuildSearchPaths) AppDomain.CurrentDomain.AssemblyResolve += s_registeredHandler; #else - s_registeredHandler = (_, assemblyName) => - { - return TryLoadAssembly(assemblyName); - }; + s_registeredHandler = (_, assemblyName) => TryLoadAssembly(assemblyName); AssemblyLoadContext.Default.Resolving += s_registeredHandler; #endif @@ -267,9 +252,9 @@ Assembly TryLoadAssembly(AssemblyName assemblyName) // Look in the MSBuild folder for any unresolved reference. It may be a dependency // of MSBuild or a task. - foreach (string msbuildPath in msbuildSearchPaths) + foreach (string msBuildPath in msbuildSearchPaths) { - string targetAssembly = Path.Combine(msbuildPath, assemblyName.Name + ".dll"); + string targetAssembly = Path.Combine(msBuildPath, assemblyName.Name + ".dll"); if (File.Exists(targetAssembly)) { assembly = Assembly.LoadFrom(targetAssembly); @@ -310,7 +295,7 @@ private static void ApplyDotNetSdkEnvironmentVariables(string dotNetSdkPath) [MSBuildSDKsPath] = Path.Combine(dotNetSdkPath, "Sdks") }; - foreach (var kvp in variables) + foreach (KeyValuePair kvp in variables) { Environment.SetEnvironmentVariable(kvp.Key, kvp.Value); } @@ -325,16 +310,16 @@ private static bool IsMSBuildAssembly(AssemblyName assemblyName) return false; } - var publicKeyToken = assemblyName.GetPublicKeyToken(); + byte[] publicKeyToken = assemblyName.GetPublicKeyToken(); if (publicKeyToken == null || publicKeyToken.Length == 0) { return false; } - var sb = new StringBuilder(); - foreach (var b in publicKeyToken) + StringBuilder sb = new StringBuilder(); + foreach (byte b in publicKeyToken) { - sb.Append($"{b:x2}"); + _ = sb.Append($"{b:x2}"); } return sb.ToString().Equals(MSBuildPublicKeyToken, StringComparison.OrdinalIgnoreCase); @@ -343,45 +328,50 @@ private static bool IsMSBuildAssembly(AssemblyName assemblyName) private static IEnumerable GetInstances(VisualStudioInstanceQueryOptions options) { #if NET46 - var devConsole = GetDevConsoleInstance(); + VisualStudioInstance devConsole = GetDevConsoleInstance(); if (devConsole != null) + { yield return devConsole; + } - #if FEATURE_VISUALSTUDIOSETUP - foreach (var instance in VisualStudioLocationHelper.GetInstances()) +#if FEATURE_VISUALSTUDIOSETUP + foreach (VisualStudioInstance instance in VisualStudioLocationHelper.GetInstances()) + { yield return instance; - #endif + } +#endif #endif #if NETCOREAPP - foreach (var dotnetSdk in DotNetSdkLocationHelper.GetInstances(options.WorkingDirectory)) + foreach (VisualStudioInstance dotnetSdk in DotNetSdkLocationHelper.GetInstances(options.WorkingDirectory)) + { yield return dotnetSdk; + } #endif } #if NET46 private static VisualStudioInstance GetDevConsoleInstance() { - var path = Environment.GetEnvironmentVariable("VSINSTALLDIR"); + string path = Environment.GetEnvironmentVariable("VSINSTALLDIR"); if (!string.IsNullOrEmpty(path)) { - var versionString = Environment.GetEnvironmentVariable("VSCMD_VER"); - Version version; - Version.TryParse(versionString, out version); + string versionString = Environment.GetEnvironmentVariable("VSCMD_VER"); + _ = Version.TryParse(versionString, out Version version); if (version == null && versionString?.Contains('-') == true) { versionString = versionString.Substring(0, versionString.IndexOf('-')); - Version.TryParse(versionString, out version); + _ = Version.TryParse(versionString, out version); } if (version == null) { versionString = Environment.GetEnvironmentVariable("VisualStudioVersion"); - Version.TryParse(versionString, out version); + _ = Version.TryParse(versionString, out version); } - if(version != null) + if (version != null) { return new VisualStudioInstance("DEVCONSOLE", path, version, DiscoveryType.DeveloperConsole); } diff --git a/src/MSBuildLocator/NativeMethods.cs b/src/MSBuildLocator/NativeMethods.cs index b42277ce..c5175eb6 100644 --- a/src/MSBuildLocator/NativeMethods.cs +++ b/src/MSBuildLocator/NativeMethods.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; using System.Runtime.InteropServices; diff --git a/src/MSBuildLocator/Properties/AssemblyInfo.cs b/src/MSBuildLocator/Properties/AssemblyInfo.cs index 074d5ee6..1956652e 100644 --- a/src/MSBuildLocator/Properties/AssemblyInfo.cs +++ b/src/MSBuildLocator/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Microsoft.Build.Locator.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100adad416086fc859fe034cc45ba1ae17cbcaa8d471c5884ef08af87f7cd4e1bbb663e1387f24bbc479d913f125643e19d6da998b0b31a2979abcd36a858756676a65f36b27d6b6a3fd330e20ed5f73da134938bbbf90276d1fcf2f887e44e0eca4d767e147d95220433e5a4e14dcb6e6cea955e360a53642985b407a63e21f0ab")] \ No newline at end of file +[assembly: InternalsVisibleTo("Microsoft.Build.Locator.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100adad416086fc859fe034cc45ba1ae17cbcaa8d471c5884ef08af87f7cd4e1bbb663e1387f24bbc479d913f125643e19d6da998b0b31a2979abcd36a858756676a65f36b27d6b6a3fd330e20ed5f73da134938bbbf90276d1fcf2f887e44e0eca4d767e147d95220433e5a4e14dcb6e6cea955e360a53642985b407a63e21f0ab")] diff --git a/src/MSBuildLocator/Utils/SemanticVersion.cs b/src/MSBuildLocator/Utils/SemanticVersion.cs index 4a3bcb11..491cec1d 100644 --- a/src/MSBuildLocator/Utils/SemanticVersion.cs +++ b/src/MSBuildLocator/Utils/SemanticVersion.cs @@ -1,17 +1,16 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Linq; -namespace Microsoft.Build.Locator +namespace Microsoft.Build.Locator.Utils { internal class SemanticVersion : IComparable { private readonly IEnumerable _releaseLabels; - private Version _version; - private string _originalValue; + private readonly Version _version; public SemanticVersion(Version version, IEnumerable releaseLabels, string originalValue) { @@ -22,7 +21,7 @@ public SemanticVersion(Version version, IEnumerable releaseLabels, strin _releaseLabels = releaseLabels.ToArray(); } - _originalValue = originalValue; + OriginalValue = originalValue; } /// @@ -45,12 +44,12 @@ public SemanticVersion(Version version, IEnumerable releaseLabels, strin /// public IEnumerable ReleaseLabels => _releaseLabels ?? Enumerable.Empty(); - public string OriginalValue => _originalValue; + public string OriginalValue { get; } /// /// The full pre-release label for the version. /// - public string Release => _releaseLabels != null ? String.Join(".", _releaseLabels) : String.Empty; + public string Release => _releaseLabels != null ? string.Join(".", _releaseLabels) : string.Empty; /// /// True if pre-release labels exist for the version. @@ -61,8 +60,8 @@ public bool IsPrerelease { if (ReleaseLabels != null) { - var enumerator = ReleaseLabels.GetEnumerator(); - return (enumerator.MoveNext() && !String.IsNullOrEmpty(enumerator.Current)); + IEnumerator enumerator = ReleaseLabels.GetEnumerator(); + return enumerator.MoveNext() && !string.IsNullOrEmpty(enumerator.Current); } return false; @@ -72,10 +71,6 @@ public bool IsPrerelease /// /// Compare versions. /// - public int CompareTo(SemanticVersion other) - { - var comparer = new VersionComparer(); - return comparer.Compare(this, other); - } + public int CompareTo(SemanticVersion other) => VersionComparer.Compare(this, other); } } diff --git a/src/MSBuildLocator/Utils/SemanticVersionParser.cs b/src/MSBuildLocator/Utils/SemanticVersionParser.cs index 9bea0025..d3ebb46c 100644 --- a/src/MSBuildLocator/Utils/SemanticVersionParser.cs +++ b/src/MSBuildLocator/Utils/SemanticVersionParser.cs @@ -1,10 +1,11 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. #if NETCOREAPP using System; using System.Linq; +using Microsoft.Build.Locator.Utils; namespace Microsoft.Build.Locator { @@ -24,7 +25,7 @@ public static bool TryParse(string value, out SemanticVersion version) if (value != null) { - var (versionString, releaseLabels) = ParseSections(value); + (string versionString, string[] releaseLabels) = ParseSections(value); if (Version.TryParse(versionString, out Version systemVersion)) { @@ -166,4 +167,4 @@ private static Version NormalizeVersionValue(Version version) } } } -#endif \ No newline at end of file +#endif diff --git a/src/MSBuildLocator/Utils/VersionComparer.cs b/src/MSBuildLocator/Utils/VersionComparer.cs index b5dabba2..3d065696 100644 --- a/src/MSBuildLocator/Utils/VersionComparer.cs +++ b/src/MSBuildLocator/Utils/VersionComparer.cs @@ -1,34 +1,34 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; -namespace Microsoft.Build.Locator +namespace Microsoft.Build.Locator.Utils { - internal sealed class VersionComparer + internal sealed class VersionComparer { /// /// Determines if both versions are equal. /// - public bool Equals(SemanticVersion x, SemanticVersion y) => Compare(x, y) == 0; + public static bool Equals(SemanticVersion x, SemanticVersion y) => Compare(x, y) == 0; /// /// Compare versions. /// - public int Compare(SemanticVersion x, SemanticVersion y) + public static int Compare(SemanticVersion x, SemanticVersion y) { - if (Object.ReferenceEquals(x, y)) + if (ReferenceEquals(x, y)) { return 0; } - if (Object.ReferenceEquals(y, null)) + if (y is null) { return 1; } - if (Object.ReferenceEquals(x, null)) + if (x is null) { return -1; } @@ -40,7 +40,7 @@ public int Compare(SemanticVersion x, SemanticVersion y) if (result != 0) { return result; - } + } result = x.Minor.CompareTo(y.Minor); if (result != 0) @@ -96,20 +96,20 @@ private static int CompareReleaseLabels(IEnumerable version1, IEnumerabl if (!aExists && bExists) { return -1; - } + } if (aExists && !bExists) { return 1; } - + result = CompareRelease(a.Current, b.Current); if (result != 0) { return result; } - + aExists = a.MoveNext(); bExists = b.MoveNext(); } @@ -126,8 +126,8 @@ private static int CompareRelease(string version1, string version2) int result; // check if the identifiers are numeric - bool v1IsNumeric = Int32.TryParse(version1, out int version1Num); - bool v2IsNumeric = Int32.TryParse(version2, out int version2Num); + bool v1IsNumeric = int.TryParse(version1, out int version1Num); + bool v2IsNumeric = int.TryParse(version2, out int version2Num); // if both are numeric compare them as numbers if (v1IsNumeric && v2IsNumeric) diff --git a/src/MSBuildLocator/VisualStudioInstance.cs b/src/MSBuildLocator/VisualStudioInstance.cs index e8185dec..1b2e39ad 100644 --- a/src/MSBuildLocator/VisualStudioInstance.cs +++ b/src/MSBuildLocator/VisualStudioInstance.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; using System.IO; @@ -60,4 +60,4 @@ internal VisualStudioInstance(string name, string path, Version version, Discove /// public DiscoveryType DiscoveryType { get; } } -} \ No newline at end of file +} diff --git a/src/MSBuildLocator/VisualStudioInstanceQueryOptions.cs b/src/MSBuildLocator/VisualStudioInstanceQueryOptions.cs index 3c257d85..b1dfc474 100644 --- a/src/MSBuildLocator/VisualStudioInstanceQueryOptions.cs +++ b/src/MSBuildLocator/VisualStudioInstanceQueryOptions.cs @@ -1,5 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. using System; diff --git a/src/MSBuildLocator/VisualStudioLocationHelper.cs b/src/MSBuildLocator/VisualStudioLocationHelper.cs index 87d1c22d..9415b239 100644 --- a/src/MSBuildLocator/VisualStudioLocationHelper.cs +++ b/src/MSBuildLocator/VisualStudioLocationHelper.cs @@ -1,5 +1,6 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + // Taken from https://github.com/Microsoft/msbuild/blob/6851538897f5d7b08024a6d8435bc44be5869e53/src/Shared/VisualStudioLocationHelper.cs #if FEATURE_VISUALSTUDIOSETUP @@ -18,7 +19,7 @@ namespace Microsoft.Build.Locator /// internal class VisualStudioLocationHelper { - private const int REGDB_E_CLASSNOTREG = unchecked((int) 0x80040154); + private const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154); /// /// Query the Visual Studio setup API to get instances of Visual Studio installed @@ -32,8 +33,8 @@ internal static IList GetInstances() try { // This code is not obvious. See the sample (link above) for reference. - var query = (ISetupConfiguration2) GetQuery(); - var e = query.EnumAllInstances(); + var query = (ISetupConfiguration2)GetQuery(); + IEnumSetupInstances e = query.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; @@ -41,13 +42,18 @@ internal static IList GetInstances() { // Call e.Next to query for the next instance (single item or nothing returned). e.Next(1, instances, out fetched); - if (fetched <= 0) continue; + if (fetched <= 0) + { + continue; + } - var instance = (ISetupInstance2) instances[0]; + var instance = (ISetupInstance2)instances[0]; InstanceState state = instance.GetState(); if (!Version.TryParse(instance.GetInstallationVersion(), out Version version)) + { continue; + } // If the install was complete and a valid version, consider it. if (state == InstanceState.Complete || @@ -96,19 +102,15 @@ private static ISetupConfiguration GetQuery() catch (COMException ex) when (ex.ErrorCode == REGDB_E_CLASSNOTREG) { // Try to get the class object using app-local call. - ISetupConfiguration query; - var result = GetSetupConfiguration(out query, IntPtr.Zero); - - if (result < 0) - throw new COMException($"Failed to get {nameof(query)}", result); + int result = GetSetupConfiguration(out ISetupConfiguration query, IntPtr.Zero); - return query; + return result < 0 ? throw new COMException($"Failed to get {nameof(query)}", result) : query; } } [DllImport("Microsoft.VisualStudio.Setup.Configuration.Native.dll", ExactSpelling = true, PreserveSig = true)] private static extern int GetSetupConfiguration( - [MarshalAs(UnmanagedType.Interface)] [Out] out ISetupConfiguration configuration, + [MarshalAs(UnmanagedType.Interface)][Out] out ISetupConfiguration configuration, IntPtr reserved); } } From e0a2f8ee829530f8aababf2b84fcd91d2cb4ee02 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> Date: Wed, 30 Aug 2023 15:40:16 +0200 Subject: [PATCH 2/2] Update version.json to 1.6 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 7be7349f..ca200cb2 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { - "version": "1.5", + "version": "1.6", "assemblyVersion": "1.0.0.0", "publicReleaseRefSpec": [ "^refs/heads/release/.*"