From db8b1e4e4e1d5975b386bbf46e18cd889a166c55 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 17 Oct 2022 18:13:58 -0700 Subject: [PATCH 001/261] Create basic initial LSP server project and extension code to connect to it --- src/Features/LanguageServer/.editorconfig | 315 ++++++++++++++++++ .../LanguageServer/Directory.Packages.props | 9 + .../Microsoft.CodeAnalysis.LanguageServer.sln | 30 ++ .../JsonRpcServer.cs | 46 +++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 17 + .../Program.cs | 34 ++ src/Features/LanguageServer/global.json | 5 + 7 files changed, 456 insertions(+) create mode 100644 src/Features/LanguageServer/.editorconfig create mode 100644 src/Features/LanguageServer/Directory.Packages.props create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs create mode 100644 src/Features/LanguageServer/global.json diff --git a/src/Features/LanguageServer/.editorconfig b/src/Features/LanguageServer/.editorconfig new file mode 100644 index 0000000000000..8764c02269b17 --- /dev/null +++ b/src/Features/LanguageServer/.editorconfig @@ -0,0 +1,315 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = false + +# Don't use tabs for indentation. +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +insert_final_newline = true +charset = utf-8-bom + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 4 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# Powershell files +[*.ps1] +indent_size = 2 + +# Shell script files +[*.sh] +end_of_line = lf +indent_size = 2 + +# Dotnet code style settings: +[*.{cs,vb}] + +# IDE0055: Fix formatting +dotnet_diagnostic.IDE0055.severity = warning + +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:refactoring +dotnet_style_qualification_for_property = false:refactoring +dotnet_style_qualification_for_method = false:refactoring +dotnet_style_qualification_for_event = false:refactoring + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Suggest more modern language features when available +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +# Whitespace options +dotnet_style_allow_multiple_blank_lines_experimental = false + +# Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static + +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case + +# Non-private readonly fields are PascalCase +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly + +dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case + +# Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const + +dotnet_naming_style.constant_style.capitalization = pascal_case + +# Static fields are camelCase and start with s_ +dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields +dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style + +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static + +dotnet_naming_style.static_field_style.capitalization = camel_case +dotnet_naming_style.static_field_style.required_prefix = s_ + +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style + +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local + +dotnet_naming_style.camel_case_style.capitalization = camel_case + +# Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function + +dotnet_naming_style.local_function_style.capitalization = pascal_case + +# By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.all_members.applicable_kinds = * + +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# error RS2008: Enable analyzer release tracking for the analyzer project containing rule '{0}' +dotnet_diagnostic.RS2008.severity = none + +# IDE0073: File header +dotnet_diagnostic.IDE0073.severity = warning +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.\nSee the LICENSE file in the project root for more information. + +# IDE0035: Remove unreachable code +dotnet_diagnostic.IDE0035.severity = warning + +# IDE0036: Order modifiers +dotnet_diagnostic.IDE0036.severity = warning + +# IDE0043: Format string contains invalid placeholder +dotnet_diagnostic.IDE0043.severity = warning + +# IDE0044: Make field readonly +dotnet_diagnostic.IDE0044.severity = warning + +# CONSIDER: Are IDE0051 and IDE0052 too noisy to be warnings for IDE editing scenarios? Should they be made build-only warnings? +# IDE0051: Remove unused private member +dotnet_diagnostic.IDE0051.severity = warning + +# IDE0170: Prefer extended property pattern +dotnet_diagnostic.IDE0170.severity = warning + +# RS0016: Only enable if API files are present +dotnet_public_api_analyzer.require_api_files = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +end_of_line = crlf +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_auto_properties = true:warning +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:warning + +# CSharp code style settings: +[*.cs] +# Newline settings +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 = flush_left + +# Whitespace options +csharp_style_allow_embedded_statements_on_same_line_experimental = false +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false + +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Prefer method-like constructs to have a block body +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none + +# Prefer property-like constructs to have an expression-body +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Suggest more modern language features when available +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 +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion + +# 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 + +# Blocks are allowed +csharp_prefer_braces = true:silent +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true +csharp_using_directive_placement = outside_namespace:suggestion +csharp_prefer_simple_using_statement = false:suggestion +csharp_style_namespace_declarations = file_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_lambdas = true:warning +csharp_style_expression_bodied_local_functions = false:warning + +[*.{cs,vb}] + +# IDE0011: Add braces +csharp_prefer_braces = when_multiline:warning +# NOTE: We need the below severity entry for Add Braces due to https://github.com/dotnet/roslyn/issues/44201 +dotnet_diagnostic.IDE0011.severity = warning + +# IDE0040: Add accessibility modifiers +dotnet_diagnostic.IDE0040.severity = warning + +# IDE0052: Remove unread private member +dotnet_diagnostic.IDE0052.severity = warning + +# IDE0059: Unnecessary assignment to a value +dotnet_diagnostic.IDE0059.severity = warning + +# IDE0060: Remove unused parameter +dotnet_diagnostic.IDE0060.severity = warning + +# CA1012: Abstract types should not have public constructors +dotnet_diagnostic.CA1012.severity = warning + +# CA1822: Make member static +dotnet_diagnostic.CA1822.severity = warning + +# Prefer "var" everywhere +dotnet_diagnostic.IDE0007.severity = warning +csharp_style_var_for_built_in_types = true:warning +csharp_style_var_when_type_is_apparent = true:warning +csharp_style_var_elsewhere = true:warning + +# dotnet_style_allow_multiple_blank_lines_experimental +dotnet_diagnostic.IDE2000.severity = warning + +# csharp_style_allow_embedded_statements_on_same_line_experimental +dotnet_diagnostic.IDE2001.severity = warning + +# csharp_style_allow_blank_lines_between_consecutive_braces_experimental +dotnet_diagnostic.IDE2002.severity = warning + +# dotnet_style_allow_statement_immediately_after_block_experimental +dotnet_diagnostic.IDE2003.severity = warning + +# csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental +dotnet_diagnostic.IDE2004.severity = warning + +[src/{VisualStudio}/**/*.{cs,vb}] +# CA1822: Make member static +# There is a risk of accidentally breaking an internal API that partners rely on though IVT. +dotnet_code_quality.CA1822.api_surface = private \ No newline at end of file diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props new file mode 100644 index 0000000000000..660884716af9a --- /dev/null +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -0,0 +1,9 @@ + + + + 6.0.0 + 6.0.2 + $(MicrosoftExtensionsLoggingVersion) + 2.12.27 + + \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln new file mode 100644 index 0000000000000..5c1f5fb200232 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer", "Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj", "{2A3C94F7-5B5E-4CDC-B645-672815E61DEB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6BB63E09-D5FD-4EF7-8041-1150449A6058}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AF07446F-2FE6-4DFD-A110-ABFB60F5FB83} + EndGlobalSection +EndGlobal diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs new file mode 100644 index 0000000000000..2d57e6b8f1a6b --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; +using StreamJsonRpc; + +namespace Microsoft.CodeAnalysis.LanguageServer; +internal sealed class JsonRpcServer : IDisposable +{ + private readonly JsonRpc _jsonRpc; + private readonly ILogger _logger; + + public JsonRpcServer(Stream inputStream, Stream outputStream, ILogger logger) + { + _logger = logger; + + var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, new JsonMessageFormatter()); + _jsonRpc = new JsonRpc(handler) + { + ExceptionStrategy = ExceptionProcessing.CommonErrorData, + }; + + _jsonRpc.AddLocalRpcTarget(this); + } + + public Task StartAsync() + { + _logger.LogInformation("Running server..."); + _jsonRpc.StartListening(); + return _jsonRpc.Completion; + } + + [JsonRpcMethod("initialize", UseSingleObjectParameterDeserialization = true)] + public Task InitializeAsync(JToken initializeParams, CancellationToken _) + { + _logger.LogInformation($"Initialize request with client capabilities: {initializeParams}"); + return Task.FromResult("hello there"); + } + + public void Dispose() + { + _jsonRpc.Dispose(); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj new file mode 100644 index 0000000000000..92d2a0b6bc759 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -0,0 +1,17 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs new file mode 100644 index 0000000000000..edce26cf85393 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.Extensions.Logging; + +using System.Diagnostics; + +Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; + +// TODO - Decide how and where we're logging. For now just logging stderr (vscode reads stdout for LSP messages). +// 1. File logs for feedback +// 2. Logs to vscode output window. +// 3. Telemetry +// https://github.com/microsoft/vscode-csharp-next/issues/12 +using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole((options) => options.LogToStandardErrorThreshold = LogLevel.Trace)); +var logger = loggerFactory.CreateLogger(); + +LaunchDebuggerIfEnabled(args); + +var jsonRpc = new JsonRpcServer(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger); + +await jsonRpc.StartAsync(); + +void LaunchDebuggerIfEnabled(string[] args) +{ + if (args.Contains("--debug") && !Debugger.IsAttached) + { + logger.LogInformation("Launching debugger..."); + _ = Debugger.Launch(); + } +} + diff --git a/src/Features/LanguageServer/global.json b/src/Features/LanguageServer/global.json new file mode 100644 index 0000000000000..ac9ad9e7a0053 --- /dev/null +++ b/src/Features/LanguageServer/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "7.0.100-rc.2" + } +} \ No newline at end of file From 790358bfdc3f8951ea77a7c8d12eca842a9e2ffc Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 20 Oct 2022 17:21:14 -0700 Subject: [PATCH 002/261] Small feedback from last PR --- .../Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs | 5 +++-- .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs index 2d57e6b8f1a6b..8bd26f1971543 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs @@ -7,12 +7,13 @@ using StreamJsonRpc; namespace Microsoft.CodeAnalysis.LanguageServer; -internal sealed class JsonRpcServer : IDisposable + +internal sealed class RoslynLanguageServer : IDisposable { private readonly JsonRpc _jsonRpc; private readonly ILogger _logger; - public JsonRpcServer(Stream inputStream, Stream outputStream, ILogger logger) + public RoslynLanguageServer(Stream inputStream, Stream outputStream, ILogger logger) { _logger = logger; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index edce26cf85393..7c21462287f58 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -2,11 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.Extensions.Logging; -using System.Diagnostics; - Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; // TODO - Decide how and where we're logging. For now just logging stderr (vscode reads stdout for LSP messages). @@ -19,10 +18,12 @@ LaunchDebuggerIfEnabled(args); -var jsonRpc = new JsonRpcServer(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger); +var jsonRpc = new RoslynLanguageServer(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger); await jsonRpc.StartAsync(); +return; + void LaunchDebuggerIfEnabled(string[] args) { if (args.Contains("--debug") && !Debugger.IsAttached) From e05884f0bd0271739d806ffbefdcc32f5f62f9aa Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 20 Oct 2022 17:33:00 -0700 Subject: [PATCH 003/261] Specify full version number --- src/Features/LanguageServer/global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/global.json b/src/Features/LanguageServer/global.json index ac9ad9e7a0053..52534e2d8a98e 100644 --- a/src/Features/LanguageServer/global.json +++ b/src/Features/LanguageServer/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "7.0.100-rc.2" + "version": "7.0.100-rc.2.22477.23" } } \ No newline at end of file From 7ed022533d89cca219ead2e421689a798c3d27b1 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 21 Oct 2022 17:06:03 -0700 Subject: [PATCH 004/261] Instantiate the roslyn LSP server with text sync support --- .../LanguageServer/Directory.Build.props | 8 ++ .../LanguageServer/Directory.Packages.props | 2 + .../Microsoft.CodeAnalysis.LanguageServer.sln | 2 + .../ExportProviderBuilder.cs | 69 ++++++++++++++++++ .../HostLspLogger.cs | 27 +++++++ .../JsonRpcServer.cs | 47 ------------ .../LanguageServer/LanguageServerHost.cs | 45 ++++++++++++ .../ServerCapabilitiesProvider.cs | 21 ++++++ .../WorkspaceRegistrationService.cs | 16 ++++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 2 + .../Program.cs | 10 ++- src/Features/LanguageServer/NuGet.config | 14 ++++ src/Features/LanguageServer/snk/keypair.snk | Bin 0 -> 596 bytes 13 files changed, 214 insertions(+), 49 deletions(-) create mode 100644 src/Features/LanguageServer/Directory.Build.props create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs delete mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs create mode 100644 src/Features/LanguageServer/NuGet.config create mode 100644 src/Features/LanguageServer/snk/keypair.snk diff --git a/src/Features/LanguageServer/Directory.Build.props b/src/Features/LanguageServer/Directory.Build.props new file mode 100644 index 0000000000000..1f5c27516c0a5 --- /dev/null +++ b/src/Features/LanguageServer/Directory.Build.props @@ -0,0 +1,8 @@ + + + + true + $(MSBuildThisFileDirectory)\snk\keypair.snk + true + + diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 660884716af9a..13dded8138209 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -1,9 +1,11 @@ + 4.5.0-dev 6.0.0 6.0.2 $(MicrosoftExtensionsLoggingVersion) + 17.2.41 2.12.27 \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln index 5c1f5fb200232..d02ffd16ebdb7 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln @@ -8,6 +8,8 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6BB63E09-D5FD-4EF7-8041-1150449A6058}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + Directory.Build.props = Directory.Build.props + NuGet.config = NuGet.config EndProjectSection EndProject Global diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs new file mode 100644 index 0000000000000..cc531826f9e56 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Reflection; +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.LanguageServer; +internal class ExportProviderBuilder +{ + /// + /// These assemblies won't necessarily be loaded when we want to run MEF discovery. + /// We'll need to add them to the catalog manually. + /// + private static readonly ImmutableHashSet AssembliesToDiscover = ImmutableHashSet.Create( + "Microsoft.CodeAnalysis.LanguageServer.Protocol.dll", + "Microsoft.CodeAnalysis.Features.dll", + "Microsoft.CodeAnalysis.Workspaces.dll"); + + public static async Task CreateExportProviderAsync(ILogger logger) + { + var baseDirectory = AppContext.BaseDirectory; + var assembliesWithFullPath = AssembliesToDiscover.Select(a => Path.Combine(baseDirectory, a)); + + var discovery = PartDiscovery.Combine( + new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) + new AttributedPartDiscoveryV1(Resolver.DefaultInstance)); + + // TODO - we should likely cache the catalog so we don't have to rebuild it every time. + var catalog = ComposableCatalog.Create(Resolver.DefaultInstance) + .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly())) + .AddParts(await discovery.CreatePartsAsync(assembliesWithFullPath)) + .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import + + if (catalog.DiscoveredParts.DiscoveryErrors.Any()) + { + foreach (var exception in catalog.DiscoveredParts.DiscoveryErrors) + { + logger.LogWarning(exception, exception.Message); + } + } + + // Assemble the parts into a valid graph. + var config = CompositionConfiguration.Create(catalog); + + if (config.CompositionErrors.Any()) + { + foreach (var errorCollection in config.CompositionErrors) + { + foreach (var error in errorCollection) + { + logger.LogInformation(error.Message); + } + } + } + + // Prepare an ExportProvider factory based on this graph. + var exportProviderFactory = config.CreateExportProviderFactory(); + + // Create an export provider, which represents a unique container of values. + // You can create as many of these as you want, but typically an app needs just one. + var exportProvider = exportProviderFactory.CreateExportProvider(); + + // Obtain our first exported value + return exportProvider; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs new file mode 100644 index 0000000000000..0c06e27db9b4a --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer; +internal class HostLspLogger : ILspServiceLogger +{ + private readonly ILogger _logger; + public HostLspLogger(ILogger logger) + { + _logger = logger; + } + + public void LogEndContext(string message, params object[] @params) => _logger.LogTrace($"[{DateTime.UtcNow:hh:mm:ss.fff}][End]{message}", @params); + + public void LogError(string message, params object[] @params) => _logger.LogError(message, @params); + + public void LogException(Exception exception, string? message = null, params object[] @params) => _logger.LogError(exception, message, @params); + + public void LogInformation(string message, params object[] @params) => _logger.LogInformation(message, @params); + + public void LogStartContext(string message, params object[] @params) => _logger.LogTrace($"[{DateTime.UtcNow:hh:mm:ss.fff}][Start]{message}", @params); + + public void LogWarning(string message, params object[] @params) => _logger.LogWarning(message, @params); +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs deleted file mode 100644 index 8bd26f1971543..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/JsonRpcServer.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; -using StreamJsonRpc; - -namespace Microsoft.CodeAnalysis.LanguageServer; - -internal sealed class RoslynLanguageServer : IDisposable -{ - private readonly JsonRpc _jsonRpc; - private readonly ILogger _logger; - - public RoslynLanguageServer(Stream inputStream, Stream outputStream, ILogger logger) - { - _logger = logger; - - var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, new JsonMessageFormatter()); - _jsonRpc = new JsonRpc(handler) - { - ExceptionStrategy = ExceptionProcessing.CommonErrorData, - }; - - _jsonRpc.AddLocalRpcTarget(this); - } - - public Task StartAsync() - { - _logger.LogInformation("Running server..."); - _jsonRpc.StartListening(); - return _jsonRpc.Completion; - } - - [JsonRpcMethod("initialize", UseSingleObjectParameterDeserialization = true)] - public Task InitializeAsync(JToken initializeParams, CancellationToken _) - { - _logger.LogInformation($"Initialize request with client capabilities: {initializeParams}"); - return Task.FromResult("hello there"); - } - - public void Dispose() - { - _jsonRpc.Dispose(); - } -} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs new file mode 100644 index 0000000000000..d5159ea71bdd3 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; +using Microsoft.CommonLanguageServerProtocol.Framework; +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Composition; +using StreamJsonRpc; + +namespace Microsoft.CodeAnalysis.LanguageServer; + +internal sealed class LanguageServerHost +{ + private readonly JsonRpc _jsonRpc; + private readonly ILogger _logger; + private readonly AbstractLanguageServer _roslynLanguageServer; + + public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logger, ExportProvider exportProvider) + { + _logger = logger; + + var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, new JsonMessageFormatter()); + + // JsonRpc disconnect / disposal is handled by AbstractLanguageServer. + _jsonRpc = new JsonRpc(handler) + { + ExceptionStrategy = ExceptionProcessing.CommonErrorData, + }; + + var roslynLspFactory = exportProvider.GetExportedValue(); + var capabilitiesProvider = new ServerCapabilitiesProvider(); + var lspLogger = new HostLspLogger(logger); + _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger); + } + + public async Task StartAsync() + { + _logger.LogInformation("Running server..."); + _jsonRpc.StartListening(); + await _jsonRpc.Completion; + await _roslynLanguageServer.WaitForExitAsync(); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs new file mode 100644 index 0000000000000..e48305d1808c5 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; +internal class ServerCapabilitiesProvider : ICapabilitiesProvider +{ + public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) + { + return new ServerCapabilities + { + TextDocumentSync = new TextDocumentSyncOptions + { + Change = TextDocumentSyncKind.Incremental, + OpenClose = true, + } + }; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs new file mode 100644 index 0000000000000..d876334ddc90a --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; + +namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; + +[Export(typeof(LspWorkspaceRegistrationService))] +internal class WorkspaceRegistrationService : LspWorkspaceRegistrationService +{ + public override string GetHostWorkspaceKind() + { + return WorkspaceKind.Host; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 92d2a0b6bc759..7d63cff24dcfc 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -8,10 +8,12 @@ + + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 7c21462287f58..3ff316222295a 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -12,13 +12,19 @@ // 1. File logs for feedback // 2. Logs to vscode output window. // 3. Telemetry +// Also decide how we configure logging (env variables, extension settings, etc.) // https://github.com/microsoft/vscode-csharp-next/issues/12 -using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole((options) => options.LogToStandardErrorThreshold = LogLevel.Trace)); +using var loggerFactory = LoggerFactory.Create(builder => +{ + _ = builder.SetMinimumLevel(LogLevel.Trace); + _ = builder.AddConsole((options) => options.LogToStandardErrorThreshold = LogLevel.Trace); +}); var logger = loggerFactory.CreateLogger(); LaunchDebuggerIfEnabled(args); -var jsonRpc = new RoslynLanguageServer(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger); +var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(logger); +var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider); await jsonRpc.StartAsync(); diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config new file mode 100644 index 0000000000000..9368736caa2ba --- /dev/null +++ b/src/Features/LanguageServer/NuGet.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/Features/LanguageServer/snk/keypair.snk b/src/Features/LanguageServer/snk/keypair.snk new file mode 100644 index 0000000000000000000000000000000000000000..9221bdcff312327a7b5328a8f2c588263b420339 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096A^T_Z^zzAyy!=oIZp+P8_iuf=@EGR^Qhkc!qH#+;$+j!ms`YI3TR;4s?lGzd z%^|=Hlv2=(SK$H*zwe_uw;C+v)Bv14>TSTQjCcVD#;CjSZ=-@<9RhFC9m Date: Mon, 24 Oct 2022 11:02:44 -0700 Subject: [PATCH 005/261] Use real roslyn package --- src/Features/LanguageServer/Directory.Packages.props | 2 +- src/Features/LanguageServer/NuGet.config | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 13dded8138209..ccde3df3687c8 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -1,7 +1,7 @@ - 4.5.0-dev + 4.5.0-1.22524.1 6.0.0 6.0.2 $(MicrosoftExtensionsLoggingVersion) diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config index 9368736caa2ba..45053cf6d9a89 100644 --- a/src/Features/LanguageServer/NuGet.config +++ b/src/Features/LanguageServer/NuGet.config @@ -6,7 +6,6 @@ - From ebb5385e4aae70e247e535f93882644017868ba1 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 24 Oct 2022 14:58:03 -0700 Subject: [PATCH 006/261] Review feedback --- .../LanguageServer/Directory.Build.props | 5 ++++ .../ExportProviderBuilder.cs | 25 +++---------------- .../HostLspLogger.cs | 4 ++- .../LanguageServer/LanguageServerHost.cs | 8 +++--- .../ServerCapabilitiesProvider.cs | 5 ++-- .../WorkspaceRegistrationService.cs | 6 +++++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 2 +- .../Program.cs | 8 +++--- 8 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Build.props b/src/Features/LanguageServer/Directory.Build.props index 1f5c27516c0a5..e7801a7e29678 100644 --- a/src/Features/LanguageServer/Directory.Build.props +++ b/src/Features/LanguageServer/Directory.Build.props @@ -4,5 +4,10 @@ true $(MSBuildThisFileDirectory)\snk\keypair.snk true + + true + latest-All + false + true diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index cc531826f9e56..b77d9c9e42153 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -8,7 +8,8 @@ using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.LanguageServer; -internal class ExportProviderBuilder + +internal sealed class ExportProviderBuilder { /// /// These assemblies won't necessarily be loaded when we want to run MEF discovery. @@ -19,7 +20,7 @@ internal class ExportProviderBuilder "Microsoft.CodeAnalysis.Features.dll", "Microsoft.CodeAnalysis.Workspaces.dll"); - public static async Task CreateExportProviderAsync(ILogger logger) + public static async Task CreateExportProviderAsync() { var baseDirectory = AppContext.BaseDirectory; var assembliesWithFullPath = AssembliesToDiscover.Select(a => Path.Combine(baseDirectory, a)); @@ -34,27 +35,9 @@ public static async Task CreateExportProviderAsync(ILogger logge .AddParts(await discovery.CreatePartsAsync(assembliesWithFullPath)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import - if (catalog.DiscoveredParts.DiscoveryErrors.Any()) - { - foreach (var exception in catalog.DiscoveredParts.DiscoveryErrors) - { - logger.LogWarning(exception, exception.Message); - } - } - // Assemble the parts into a valid graph. var config = CompositionConfiguration.Create(catalog); - - if (config.CompositionErrors.Any()) - { - foreach (var errorCollection in config.CompositionErrors) - { - foreach (var error in errorCollection) - { - logger.LogInformation(error.Message); - } - } - } + _ = config.ThrowOnErrors(); // Prepare an ExportProvider factory based on this graph. var exportProviderFactory = config.CreateExportProviderFactory(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs index 0c06e27db9b4a..ec7cd4070d3af 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs @@ -5,9 +5,11 @@ using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.LanguageServer; -internal class HostLspLogger : ILspServiceLogger + +internal sealed class HostLspLogger : ILspServiceLogger { private readonly ILogger _logger; + public HostLspLogger(ILogger logger) { _logger = logger; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index d5159ea71bdd3..ed9c0fea1ed52 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -23,7 +23,7 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logge var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, new JsonMessageFormatter()); - // JsonRpc disconnect / disposal is handled by AbstractLanguageServer. + // If there is a jsonrpc disconnect or server shutdown, that is handled by the AbstractLanguageServer. No need to do anything here. _jsonRpc = new JsonRpc(handler) { ExceptionStrategy = ExceptionProcessing.CommonErrorData, @@ -37,9 +37,9 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logge public async Task StartAsync() { - _logger.LogInformation("Running server..."); + _logger.LogInformation("Starting server..."); _jsonRpc.StartListening(); - await _jsonRpc.Completion; - await _roslynLanguageServer.WaitForExitAsync(); + await _jsonRpc.Completion.ConfigureAwait(false); + await _roslynLanguageServer.WaitForExitAsync().ConfigureAwait(false); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs index e48305d1808c5..59ea0477f38e0 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs @@ -5,11 +5,12 @@ using Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; -internal class ServerCapabilitiesProvider : ICapabilitiesProvider + +internal sealed class ServerCapabilitiesProvider : ICapabilitiesProvider { public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) { - return new ServerCapabilities + return new() { TextDocumentSync = new TextDocumentSyncOptions { diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs index d876334ddc90a..ba75014fe88ff 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs @@ -6,11 +6,17 @@ namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; +/// +/// Implements the workspace registration service so that any new workspaces we +/// create are automatically registered by +/// [Export(typeof(LspWorkspaceRegistrationService))] internal class WorkspaceRegistrationService : LspWorkspaceRegistrationService { public override string GetHostWorkspaceKind() { + // For now mark the host workspace kind as the 'main' workspace where + // 'workspace/XXXX' requests go to. return WorkspaceKind.Host; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 7d63cff24dcfc..ff699ec6a0e80 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 3ff316222295a..528245f4d063a 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -16,17 +16,17 @@ // https://github.com/microsoft/vscode-csharp-next/issues/12 using var loggerFactory = LoggerFactory.Create(builder => { - _ = builder.SetMinimumLevel(LogLevel.Trace); - _ = builder.AddConsole((options) => options.LogToStandardErrorThreshold = LogLevel.Trace); + builder.SetMinimumLevel(LogLevel.Trace); + builder.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace); }); var logger = loggerFactory.CreateLogger(); LaunchDebuggerIfEnabled(args); -var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(logger); +var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider); -await jsonRpc.StartAsync(); +await jsonRpc.StartAsync().ConfigureAwait(false); return; From e93e22922239564a9010a7e1d906fa2389e5514f Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 24 Oct 2022 15:56:45 -0700 Subject: [PATCH 007/261] Add appropriate feed for additional dependencies --- src/Features/LanguageServer/NuGet.config | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config index 45053cf6d9a89..dfd502e64e5df 100644 --- a/src/Features/LanguageServer/NuGet.config +++ b/src/Features/LanguageServer/NuGet.config @@ -6,6 +6,7 @@ + From e4a5599034317d3235d05927ed8db0f3429c82de Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 26 Oct 2022 13:15:45 -0700 Subject: [PATCH 008/261] Add basic unit test project that runs on CI (#43) * Add basic test project * Run tests in CI * spacing * feedback --- .../LanguageServer/Directory.Build.props | 2 + .../LanguageServer/Directory.Packages.props | 1 + .../AbstractLanguageServerHostTests.cs | 82 +++++++++++++++++++ ...deAnalysis.LanguageServer.UnitTests.csproj | 29 +++++++ .../TestOutputLogger.cs | 40 +++++++++ .../Usings.cs | 5 ++ .../Microsoft.CodeAnalysis.LanguageServer.sln | 6 ++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 4 + 8 files changed, 169 insertions(+) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TestOutputLogger.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Usings.cs diff --git a/src/Features/LanguageServer/Directory.Build.props b/src/Features/LanguageServer/Directory.Build.props index e7801a7e29678..1ee7a968de2d1 100644 --- a/src/Features/LanguageServer/Directory.Build.props +++ b/src/Features/LanguageServer/Directory.Build.props @@ -9,5 +9,7 @@ latest-All false true + + 002400000480000094000000060200000024000052534131000400000100010009f3c8fcb7cb2592cc6e6d3646d4d9a2bda9e7a243d357bc17a5a06f50ed0dae74a343cd9538fe45bbc90a3f7cbecb23558205e3b246b69f7f7730e520460d560da1c68cda9e2256e3b801629e2dc1fd588b1681aaf4f2c98abcfc50086ecbcd55f76f7dbaf018e708527d8ae3a2714b3ec9b62bd9aaf56cf55b3ffc9eee31aa diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index ccde3df3687c8..967253c91c97b 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -6,6 +6,7 @@ 6.0.2 $(MicrosoftExtensionsLoggingVersion) 17.2.41 + 2.9.112 2.12.27 \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs new file mode 100644 index 0000000000000..4cad190184ac3 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Composition; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Nerdbank.Streams; +using StreamJsonRpc; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + +public abstract class AbstractLanguageServerHostTests +{ + protected readonly ILogger TestOutputLogger; + + protected AbstractLanguageServerHostTests(ITestOutputHelper testOutputHelper) + { + TestOutputLogger = new TestOutputLogger(testOutputHelper); + } + + protected Task CreateLanguageServerAsync() + { + return TestLspServer.CreateAsync(new ClientCapabilities(), TestOutputLogger); + } + + protected sealed class TestLspServer : IAsyncDisposable + { + private readonly LanguageServerHost _languageServerHost; + private readonly Task _languageServerHostCompletionTask; + private readonly JsonRpc _clientRpc; + + public static async Task CreateAsync(ClientCapabilities clientCapabilities, ILogger logger) + { + var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + var testLspServer = new TestLspServer(exportProvider, logger); + var initializeResponse = await testLspServer.ExecuteRequestAsync(Methods.InitializeName, new InitializeParams { Capabilities = clientCapabilities }, CancellationToken.None); + Assert.NotNull(initializeResponse?.Capabilities); + + await testLspServer.ExecuteRequestAsync(Methods.InitializedName, new InitializedParams(), CancellationToken.None); + + return testLspServer; + } + + private TestLspServer(ExportProvider exportProvider, ILogger logger) + { + var (clientStream, serverStream) = FullDuplexStream.CreatePair(); + _languageServerHost = new LanguageServerHost(serverStream, serverStream, logger, exportProvider); + + _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, new JsonMessageFormatter())) + { + ExceptionStrategy = ExceptionProcessing.ISerializable, + }; + + _clientRpc.StartListening(); + + // This task completes when the server shuts down. We store it so that we can wait for completion + // when we dispose of the test server. + _languageServerHostCompletionTask = _languageServerHost.StartAsync(); + } + + public async Task ExecuteRequestAsync(string methodName, RequestType request, CancellationToken cancellationToken) where RequestType : class + { + var result = await _clientRpc.InvokeWithParameterObjectAsync(methodName, request, cancellationToken: cancellationToken).ConfigureAwait(false); + return result; + } + + public async ValueTask DisposeAsync() + { + await _clientRpc.InvokeAsync(Methods.ShutdownName).ConfigureAwait(false); + await _clientRpc.NotifyAsync(Methods.ExitName).ConfigureAwait(false); + + // The language server host task should complete once shutdown and exit are called. +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks + await _languageServerHostCompletionTask.ConfigureAwait(false); +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks + + _clientRpc.Dispose(); + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj new file mode 100644 index 0000000000000..da53ec41ae5af --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj @@ -0,0 +1,29 @@ + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TestOutputLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TestOutputLogger.cs new file mode 100644 index 0000000000000..7741e6c0340ae --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TestOutputLogger.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + +internal class TestOutputLogger : ILogger +{ + private readonly ITestOutputHelper _testOutputHelper; + + public TestOutputLogger(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + public IDisposable BeginScope(TState state) + { + return new NoOpDisposable(); + } + + public bool IsEnabled(LogLevel logLevel) + { + return true; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + _testOutputHelper.WriteLine($"[{DateTime.UtcNow:hh:mm:ss.fff}][{logLevel}]{formatter(state, exception)}"); + } + + private sealed class NoOpDisposable : IDisposable + { + public void Dispose() + { + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Usings.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Usings.cs new file mode 100644 index 0000000000000..349f347431670 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Usings.cs @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +global using Xunit; \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln index d02ffd16ebdb7..c2f769134cf72 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln @@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.config = NuGet.config EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CodeAnalysis.LanguageServer.UnitTests", "Microsoft.CodeAnalysis.LanguageServer.UnitTests\Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj", "{9A90AA02-4275-40ED-B1F1-731AF17E675C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -22,6 +24,10 @@ Global {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.Build.0 = Release|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index ff699ec6a0e80..f72d2567beea3 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -16,4 +16,8 @@ + + + + From 8064d8eff86e0c389b90d50306935ab98f72e9c9 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 26 Oct 2022 14:54:39 -0700 Subject: [PATCH 009/261] Reference C# dlls needed to build the MefHostServices (#44) --- src/Features/LanguageServer/Directory.Packages.props | 4 +++- .../LanguageServer/ServerCapabilitiesProvider.cs | 3 ++- .../Microsoft.CodeAnalysis.LanguageServer.csproj | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 967253c91c97b..635a94f8e0201 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -1,7 +1,9 @@ - 4.5.0-1.22524.1 + 4.5.0-1.22524.1 + $(MicrosoftCodeAnalysisVersion) + $(MicrosoftCodeAnalysisVersion) 6.0.0 6.0.2 $(MicrosoftExtensionsLoggingVersion) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs index 59ea0477f38e0..d0468c5a71bb9 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs @@ -16,7 +16,8 @@ public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) { Change = TextDocumentSyncKind.Incremental, OpenClose = true, - } + }, + DefinitionProvider = true, }; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index f72d2567beea3..202173f2e927b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -14,6 +14,9 @@ + + + From 8486eeeef0a8fe200578b0787a51d81f1f06eefa Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 27 Oct 2022 10:25:53 -0700 Subject: [PATCH 010/261] Add back test class I accidentally deleted (#48) --- .../ServerInitializationTests.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/ServerInitializationTests.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/ServerInitializationTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/ServerInitializationTests.cs new file mode 100644 index 0000000000000..817edcb942d2e --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/ServerInitializationTests.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + +public class ServerInitializationTests : AbstractLanguageServerHostTests +{ + public ServerInitializationTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) + { + } + + [Fact] + public async Task TestServerHandlesTextSyncRequestsAsync() + { + await using var server = await CreateLanguageServerAsync(); + var document = new VersionedTextDocumentIdentifier { Uri = new Uri(@"C:\file.cs") }; + var response = await server.ExecuteRequestAsync(Methods.TextDocumentDidOpenName, new DidOpenTextDocumentParams + { + TextDocument = new TextDocumentItem + { + Uri = document.Uri, + Text = "Write" + } + }, CancellationToken.None); + + // These are notifications so we should get a null response (but no exceptions). + Assert.Null(response); + + response = await server.ExecuteRequestAsync(Methods.TextDocumentDidChangeName, new DidChangeTextDocumentParams + { + TextDocument = document, + ContentChanges = new[] + { + new TextDocumentContentChangeEvent + { + Range = new VisualStudio.LanguageServer.Protocol.Range { Start = new Position(0, 0), End = new Position(0, 0) }, + Text = "Console." + } + } + }, CancellationToken.None); + + // These are notifications so we should get a null response (but no exceptions). + Assert.Null(response); + + response = await server.ExecuteRequestAsync(Methods.TextDocumentDidCloseName, new DidCloseTextDocumentParams + { + TextDocument = document + }, CancellationToken.None); + + // These are notifications so we should get a null response (but no exceptions). + Assert.Null(response); + } +} From 7aa04c2771494614fef5b5d20fea32011e5a671c Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 31 Oct 2022 17:26:30 -0700 Subject: [PATCH 011/261] Add basic project implementation to unblock progress on LSP handlers --- .../LanguageServer/Directory.Packages.props | 3 ++ .../ExportProviderBuilder.cs | 46 +++++++++++++------ .../LanguageServer/LanguageServerHost.cs | 2 +- .../ServerCapabilitiesProvider.cs | 13 +++++- .../WorkspaceRegistrationService.cs | 10 +++- ...crosoft.CodeAnalysis.LanguageServer.csproj | 5 +- .../Program.cs | 46 ++++++++++++++++++- 7 files changed, 105 insertions(+), 20 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 635a94f8e0201..9d4d8cd0359ab 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -1,9 +1,12 @@ + 1.5.5 4.5.0-1.22524.1 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) + $(MicrosoftCodeAnalysisVersion) + $(MicrosoftCodeAnalysisVersion) 6.0.0 6.0.2 $(MicrosoftExtensionsLoggingVersion) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index b77d9c9e42153..15e04cdd62d2d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -2,28 +2,22 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Immutable; +using System.Diagnostics.Contracts; using System.Reflection; -using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.LanguageServer; internal sealed class ExportProviderBuilder { - /// - /// These assemblies won't necessarily be loaded when we want to run MEF discovery. - /// We'll need to add them to the catalog manually. - /// - private static readonly ImmutableHashSet AssembliesToDiscover = ImmutableHashSet.Create( - "Microsoft.CodeAnalysis.LanguageServer.Protocol.dll", - "Microsoft.CodeAnalysis.Features.dll", - "Microsoft.CodeAnalysis.Workspaces.dll"); - public static async Task CreateExportProviderAsync() { var baseDirectory = AppContext.BaseDirectory; - var assembliesWithFullPath = AssembliesToDiscover.Select(a => Path.Combine(baseDirectory, a)); + + // Load any Roslyn assemblies from the extension directory + var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis.*.dll"); var discovery = PartDiscovery.Combine( new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) @@ -32,12 +26,14 @@ public static async Task CreateExportProviderAsync() // TODO - we should likely cache the catalog so we don't have to rebuild it every time. var catalog = ComposableCatalog.Create(Resolver.DefaultInstance) .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly())) - .AddParts(await discovery.CreatePartsAsync(assembliesWithFullPath)) + .AddParts(await discovery.CreatePartsAsync(assembliesToDiscover)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import // Assemble the parts into a valid graph. var config = CompositionConfiguration.Create(catalog); - _ = config.ThrowOnErrors(); + + // Verify we only have expected errors. + ThrowOnUnexpectedErrors(config); // Prepare an ExportProvider factory based on this graph. var exportProviderFactory = config.CreateExportProviderFactory(); @@ -49,4 +45,28 @@ public static async Task CreateExportProviderAsync() // Obtain our first exported value return exportProvider; } + + private static void ThrowOnUnexpectedErrors(CompositionConfiguration configuration) + { + // Verify that we have exactly the MEF errors that we expect. If we have less or more this needs to be updated to assert the expected behavior. + // Currently we are expecting the following: + // "----- CompositionError level 1 ------ + // Microsoft.CodeAnalysis.CSharp.CodeRefactorings.AddMissingImports.CSharpAddMissingImportsRefactoringProvider.ctor(pasteTrackingService): expected exactly 1 export matching constraints: + // Contract name: Microsoft.CodeAnalysis.PasteTracking.IPasteTrackingService + // TypeIdentityName: Microsoft.CodeAnalysis.PasteTracking.IPasteTrackingService + // but found 0. + // part definition Microsoft.CodeAnalysis.CSharp.CodeRefactorings.AddMissingImports.CSharpAddMissingImportsRefactoringProvider + + // Microsoft.CodeAnalysis.ExternalAccess.Pythia.PythiaSignatureHelpProvider.ctor(implementation): expected exactly 1 export matching constraints: + // Contract name: Microsoft.CodeAnalysis.ExternalAccess.Pythia.Api.IPythiaSignatureHelpProviderImplementation + // TypeIdentityName: Microsoft.CodeAnalysis.ExternalAccess.Pythia.Api.IPythiaSignatureHelpProviderImplementation + // but found 0. + // part definition Microsoft.CodeAnalysis.ExternalAccess.Pythia.PythiaSignatureHelpProvider + var erroredParts = configuration.CompositionErrors.FirstOrDefault()?.SelectMany(error => error.Parts).Select(part => part.Definition.Type.Name) ?? Enumerable.Empty(); + var expectedErroredParts = new string[] { "CSharpAddMissingImportsRefactoringProvider", "PythiaSignatureHelpProvider" }; + if (erroredParts.Count() != expectedErroredParts.Length || !erroredParts.All(part => expectedErroredParts.Contains(part))) + { + configuration.ThrowOnErrors(); + } + } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index ed9c0fea1ed52..e306115a92db0 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -30,7 +30,7 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logge }; var roslynLspFactory = exportProvider.GetExportedValue(); - var capabilitiesProvider = new ServerCapabilitiesProvider(); + var capabilitiesProvider = new ServerCapabilitiesProvider(exportProvider.GetExportedValue()); var lspLogger = new HostLspLogger(logger); _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger); } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs index d0468c5a71bb9..1fdbff346b286 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs @@ -8,8 +8,16 @@ namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; internal sealed class ServerCapabilitiesProvider : ICapabilitiesProvider { + private readonly ExperimentalCapabilitiesProvider _roslynCapabilities; + + public ServerCapabilitiesProvider(ExperimentalCapabilitiesProvider roslynCapabilities) + { + _roslynCapabilities = roslynCapabilities; + } + public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) { + var roslynCapabilities = _roslynCapabilities.GetCapabilities(clientCapabilities); return new() { TextDocumentSync = new TextDocumentSyncOptions @@ -17,7 +25,10 @@ public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) Change = TextDocumentSyncKind.Incremental, OpenClose = true, }, - DefinitionProvider = true, + DefinitionProvider = roslynCapabilities.DefinitionProvider, + FoldingRangeProvider = roslynCapabilities.FoldingRangeProvider, + DocumentHighlightProvider = roslynCapabilities.DocumentHighlightProvider, + SignatureHelpProvider = roslynCapabilities.SignatureHelpProvider, }; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs index ba75014fe88ff..97e54ab2fc3d0 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs @@ -10,13 +10,19 @@ namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; /// Implements the workspace registration service so that any new workspaces we /// create are automatically registered by /// -[Export(typeof(LspWorkspaceRegistrationService))] +[Export(typeof(LspWorkspaceRegistrationService)), Shared] internal class WorkspaceRegistrationService : LspWorkspaceRegistrationService { + [ImportingConstructor] + public WorkspaceRegistrationService() + { + + } + public override string GetHostWorkspaceKind() { // For now mark the host workspace kind as the 'main' workspace where // 'workspace/XXXX' requests go to. - return WorkspaceKind.Host; + return WorkspaceKind.MSBuild; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 202173f2e927b..1b670cb5b7b21 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -8,7 +8,10 @@ + + + @@ -20,7 +23,7 @@ - + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 528245f4d063a..915e0c174b870 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -3,8 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using Microsoft.Build.Locator; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.CodeAnalysis.MSBuild; using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Composition; Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; @@ -23,10 +28,21 @@ LaunchDebuggerIfEnabled(args); +var solutionPath = GetSolutionPath(args); + +// Register and load the appropriate MSBuild assemblies before we create the MEF composition. +// This is required because we need to include types from MS.CA.Workspaces.MSBuild which has a dependency on MSBuild dlls being loaded. +var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); +MSBuildLocator.RegisterInstance(msbuildInstances.First()); + var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); -var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider); -await jsonRpc.StartAsync().ConfigureAwait(false); +using (var workspace = CreateWorkspaceAsync(solutionPath, exportProvider, logger)) +{ + var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider); + + await jsonRpc.StartAsync().ConfigureAwait(false); +} return; @@ -39,3 +55,29 @@ void LaunchDebuggerIfEnabled(string[] args) } } +static string GetSolutionPath(string[] args) +{ + var solutionPathIndex = Array.IndexOf(args, "--solutionPath") + 1; + if (solutionPathIndex == 0 || solutionPathIndex >= args.Length) + { + throw new InvalidOperationException($"Missing valid --solutionPath argument, got {string.Join(",", args)}"); + } + + return args[solutionPathIndex]; +} + +static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, ILogger logger) +{ + try + { + var msbuildWorkspace = MSBuildWorkspace.Create(MefV1HostServices.Create(exportProvider.AsExportProvider())); + await msbuildWorkspace.OpenSolutionAsync(solutionPath); + return msbuildWorkspace; + } + catch (Exception ex) + { + logger.LogError(ex, $"Failed to load workspace for {solutionPath}"); + throw; + } +} + From 9196e0eec2cab96ba979ffbf7b369d55bc8e3e0d Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 1 Nov 2022 18:32:08 -0700 Subject: [PATCH 012/261] Use new roslyn packages to fix option reading exceptions --- src/Features/LanguageServer/Directory.Packages.props | 6 ++++-- .../LanguageServer/ServerCapabilitiesProvider.cs | 3 +++ .../Microsoft.CodeAnalysis.LanguageServer.csproj | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 9d4d8cd0359ab..2f45488098abb 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,9 +2,11 @@ 1.5.5 - 4.5.0-1.22524.1 + 4.5.0-2.22552.19 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) + $(MicrosoftCodeAnalysisVersion) + $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) 6.0.0 @@ -12,6 +14,6 @@ $(MicrosoftExtensionsLoggingVersion) 17.2.41 2.9.112 - 2.12.27 + 2.13.21-alpha \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs index 1fdbff346b286..1acb470f2f1c6 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs @@ -29,6 +29,9 @@ public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) FoldingRangeProvider = roslynCapabilities.FoldingRangeProvider, DocumentHighlightProvider = roslynCapabilities.DocumentHighlightProvider, SignatureHelpProvider = roslynCapabilities.SignatureHelpProvider, + DocumentFormattingProvider = roslynCapabilities.DocumentFormattingProvider, + DocumentRangeFormattingProvider = roslynCapabilities.DocumentRangeFormattingProvider, + DocumentOnTypeFormattingProvider = roslynCapabilities.DocumentOnTypeFormattingProvider, }; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 1b670cb5b7b21..b7c2ca78c940a 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -10,6 +10,8 @@ + + From cb934f5a4e41cfb8c007d5efe698af06253e5698 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 10 Nov 2022 12:29:27 -0800 Subject: [PATCH 013/261] Enable more LSP features --- .../LanguageServer/Directory.Packages.props | 3 ++- .../LanguageServer/ServerCapabilitiesProvider.cs | 16 +--------------- .../Microsoft.CodeAnalysis.LanguageServer.csproj | 1 + 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 2f45488098abb..181601b4096b6 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,7 +2,7 @@ 1.5.5 - 4.5.0-2.22552.19 + 4.5.0-2.22559.13 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) @@ -13,6 +13,7 @@ 6.0.2 $(MicrosoftExtensionsLoggingVersion) 17.2.41 + 17.4.1012 2.9.112 2.13.21-alpha diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs index 1acb470f2f1c6..1b8b495b941ef 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/ServerCapabilitiesProvider.cs @@ -18,20 +18,6 @@ public ServerCapabilitiesProvider(ExperimentalCapabilitiesProvider roslynCapabil public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) { var roslynCapabilities = _roslynCapabilities.GetCapabilities(clientCapabilities); - return new() - { - TextDocumentSync = new TextDocumentSyncOptions - { - Change = TextDocumentSyncKind.Incremental, - OpenClose = true, - }, - DefinitionProvider = roslynCapabilities.DefinitionProvider, - FoldingRangeProvider = roslynCapabilities.FoldingRangeProvider, - DocumentHighlightProvider = roslynCapabilities.DocumentHighlightProvider, - SignatureHelpProvider = roslynCapabilities.SignatureHelpProvider, - DocumentFormattingProvider = roslynCapabilities.DocumentFormattingProvider, - DocumentRangeFormattingProvider = roslynCapabilities.DocumentRangeFormattingProvider, - DocumentOnTypeFormattingProvider = roslynCapabilities.DocumentOnTypeFormattingProvider, - }; + return roslynCapabilities; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index b7c2ca78c940a..8c06ee8dd0572 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -19,6 +19,7 @@ + From 06260326ec1d263d3ce27350ee598baa57a84ee8 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 11 Nov 2022 10:36:26 -0800 Subject: [PATCH 014/261] Upgrade to new roslyn version with fixed FAR/impl --- src/Features/LanguageServer/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 181601b4096b6..36316e5fefdb4 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,7 +2,7 @@ 1.5.5 - 4.5.0-2.22559.13 + 4.5.0-2.22560.8 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) From bd428b7124e29a263118e997bfd314475b6f928b Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 18 Nov 2022 21:49:31 -0800 Subject: [PATCH 015/261] Enable diagnostics --- .../LanguageServer/Directory.Packages.props | 6 +- .../ExportProviderBuilder.cs | 2 +- .../HostWorkspace/HostWorkspace.cs | 89 +++++++++++++++++++ .../WorkspaceRegistrationService.cs | 2 +- .../Program.cs | 19 +--- 5 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 36316e5fefdb4..5876687948caa 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,7 +2,7 @@ 1.5.5 - 4.5.0-2.22560.8 + 4.5.0-dev $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) @@ -13,8 +13,8 @@ 6.0.2 $(MicrosoftExtensionsLoggingVersion) 17.2.41 - 17.4.1012 + 17.5.18-preview-g41ec27df75 2.9.112 - 2.13.21-alpha + 2.14.6-alpha \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 15e04cdd62d2d..f8aebd95dc289 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -17,7 +17,7 @@ public static async Task CreateExportProviderAsync() var baseDirectory = AppContext.BaseDirectory; // Load any Roslyn assemblies from the extension directory - var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis.*.dll"); + var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll"); var discovery = PartDiscovery.Combine( new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs new file mode 100644 index 0000000000000..7bd878c29b45c --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs @@ -0,0 +1,89 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; +using Microsoft.CodeAnalysis.MSBuild; +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; +internal class HostWorkspace : Workspace +{ + /// + /// Set of assemblies to look for host installed analyzers. + /// Similar to https://github.com/dotnet/roslyn/blob/9fee6f5461baae5152c956c3c3024ca15b85feb9/src/VisualStudio/Setup/source.extension.vsixmanifest#L51 + /// except only include dlls applicable to VSCode. + /// + private static readonly string[] _hostAnalyzerDlls = new string[] + { + "Microsoft.CodeAnalysis.CSharp.dll", + "Microsoft.CodeAnalysis.VisualBasic.dll", + "Microsoft.CodeAnalysis.Features.dll", + "Microsoft.CodeAnalysis.Workspaces.dll", + "Microsoft.CodeAnalysis.CSharp.Workspaces.dll", + "Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll", + "Microsoft.CodeAnalysis.CSharp.Features.dll", + "Microsoft.CodeAnalysis.VisualBasic.Features.dll", + }; + + public HostWorkspace(HostServices host, string? workspaceKind) : base(host, workspaceKind) + { + } + + internal static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, ILogger logger) + { + try + { + // This is weird. Really we don't need a workspace other than it is a useful tool to keep track of LSP changes. + // But no changes should ever be applied from the LSP host (instead the client should be applying them). + // + // So we use the MSBuildWorkspace type to create the solution. But we can't use the MSBuild workspace itself + // because it doesn't support adding analyzers to the solution (and generallly we shouldn't be calling TryApplyChanges). + // Instead we just take the solution and it put in this workspace type where we can call SetCurrentSolution. + // + // This is all going to get refactored anyway when we do more project system stuff. + var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); + using var msbuildWorkspace = MSBuildWorkspace.Create(hostServices); + var solution = await msbuildWorkspace.OpenSolutionAsync(solutionPath); + + var hostWorkspace = new HostWorkspace(hostServices, WorkspaceKind.Host); + hostWorkspace.SetCurrentSolution(solution); + // SetCurrentSolution does raise workspace events. For now manually register until we figure out how workspaces will work. + exportProvider.GetExportedValue().Register(hostWorkspace); + + InitializeDiagnostics(hostWorkspace, exportProvider, logger); + + return hostWorkspace; + } + catch (Exception ex) + { + logger.LogError(ex, $"Failed to load workspace for {solutionPath}"); + throw; + } + } + + internal static void InitializeDiagnostics(HostWorkspace hostWorkspace, ExportProvider exportProvider, ILogger logger) + { + var baseDirectory = AppContext.BaseDirectory; + var references = new List(); + var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader(); + foreach (var assemblyName in _hostAnalyzerDlls) + { + var path = Path.Combine(baseDirectory, assemblyName); + if (!File.Exists(path)) + continue; + + references.Add(new AnalyzerFileReference(path, analyzerLoader)); + } + + var newSolution = hostWorkspace.CurrentSolution.WithAnalyzerReferences(references); + hostWorkspace.SetCurrentSolution(newSolution); + logger.LogDebug($"Loaded host analyzers:{Environment.NewLine}{string.Join(Environment.NewLine, references.Select(r => r.FullPath))}"); + + exportProvider.GetExportedValue().InitializeDiagnosticsServices(hostWorkspace); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs index 97e54ab2fc3d0..88919ded2703a 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs @@ -23,6 +23,6 @@ public override string GetHostWorkspaceKind() { // For now mark the host workspace kind as the 'main' workspace where // 'workspace/XXXX' requests go to. - return WorkspaceKind.MSBuild; + return WorkspaceKind.Host; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 915e0c174b870..ea3d2ec9ad94c 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -7,6 +7,8 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; +using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; using Microsoft.CodeAnalysis.MSBuild; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -37,7 +39,7 @@ var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); -using (var workspace = CreateWorkspaceAsync(solutionPath, exportProvider, logger)) +using (var workspace = await HostWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, logger)) { var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider); @@ -66,18 +68,3 @@ static string GetSolutionPath(string[] args) return args[solutionPathIndex]; } -static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, ILogger logger) -{ - try - { - var msbuildWorkspace = MSBuildWorkspace.Create(MefV1HostServices.Create(exportProvider.AsExportProvider())); - await msbuildWorkspace.OpenSolutionAsync(solutionPath); - return msbuildWorkspace; - } - catch (Exception ex) - { - logger.LogError(ex, $"Failed to load workspace for {solutionPath}"); - throw; - } -} - From da82038810e056e33ccba968633532e2804a395e Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 28 Nov 2022 14:02:58 -0800 Subject: [PATCH 016/261] Use new roslyn version --- src/Features/LanguageServer/Directory.Packages.props | 6 +++--- .../AbstractLanguageServerHostTests.cs | 4 +++- .../HostWorkspace/HostWorkspace.cs | 3 +-- .../LanguageServer/LanguageServerHost.cs | 5 +++-- .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 6 +++--- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 5876687948caa..e8f904ab561db 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,7 +2,7 @@ 1.5.5 - 4.5.0-dev + 4.5.0-2.22577.2 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) @@ -13,8 +13,8 @@ 6.0.2 $(MicrosoftExtensionsLoggingVersion) 17.2.41 - 17.5.18-preview-g41ec27df75 + 17.5.20-preview 2.9.112 - 2.14.6-alpha + 2.14.17-alpha \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs index 4cad190184ac3..9ee2fd8448eb0 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -46,7 +47,8 @@ public static async Task CreateAsync(ClientCapabilities clientCap private TestLspServer(ExportProvider exportProvider, ILogger logger) { var (clientStream, serverStream) = FullDuplexStream.CreatePair(); - _languageServerHost = new LanguageServerHost(serverStream, serverStream, logger, exportProvider); + var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); + _languageServerHost = new LanguageServerHost(serverStream, serverStream, exportProvider, hostServices, logger); _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, new JsonMessageFormatter())) { diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs index 7bd878c29b45c..4208e90ae3841 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs @@ -34,7 +34,7 @@ public HostWorkspace(HostServices host, string? workspaceKind) : base(host, work { } - internal static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, ILogger logger) + internal static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, HostServices hostServices, ILogger logger) { try { @@ -46,7 +46,6 @@ internal static async Task CreateWorkspaceAsync(string solutionPath, // Instead we just take the solution and it put in this workspace type where we can call SetCurrentSolution. // // This is all going to get refactored anyway when we do more project system stuff. - var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); using var msbuildWorkspace = MSBuildWorkspace.Create(hostServices); var solution = await msbuildWorkspace.OpenSolutionAsync(solutionPath); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index e306115a92db0..931bb5acbc3de 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CommonLanguageServerProtocol.Framework; @@ -17,7 +18,7 @@ internal sealed class LanguageServerHost private readonly ILogger _logger; private readonly AbstractLanguageServer _roslynLanguageServer; - public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logger, ExportProvider exportProvider) + public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, HostServices hostServices, ILogger logger) { _logger = logger; @@ -32,7 +33,7 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logge var roslynLspFactory = exportProvider.GetExportedValue(); var capabilitiesProvider = new ServerCapabilitiesProvider(exportProvider.GetExportedValue()); var lspLogger = new HostLspLogger(logger); - _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger); + _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices); } public async Task StartAsync() diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index ea3d2ec9ad94c..08976151dd39d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -38,10 +38,10 @@ MSBuildLocator.RegisterInstance(msbuildInstances.First()); var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); - -using (var workspace = await HostWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, logger)) +var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); +using (var workspace = await HostWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, logger)) { - var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider); + var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, logger); await jsonRpc.StartAsync().ConfigureAwait(false); } From 1efb85ba34cb98ef32c9557fe90a486d102c84fd Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 28 Nov 2022 15:39:37 -0800 Subject: [PATCH 017/261] review feedback --- ...orkspace.cs => LanguageServerWorkspace.cs} | 35 +++++++++---------- .../Program.cs | 4 +-- 2 files changed, 19 insertions(+), 20 deletions(-) rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/{HostWorkspace.cs => LanguageServerWorkspace.cs} (72%) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs similarity index 72% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs index 4208e90ae3841..e5bb7e3b17104 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs @@ -2,24 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Immutable; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; using Microsoft.CodeAnalysis.MSBuild; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; -internal class HostWorkspace : Workspace +internal class LanguageServerWorkspace : Workspace { /// /// Set of assemblies to look for host installed analyzers. /// Similar to https://github.com/dotnet/roslyn/blob/9fee6f5461baae5152c956c3c3024ca15b85feb9/src/VisualStudio/Setup/source.extension.vsixmanifest#L51 /// except only include dlls applicable to VSCode. /// - private static readonly string[] _hostAnalyzerDlls = new string[] - { + private static readonly ImmutableArray s_hostAnalyzerDlls = ImmutableArray.Create( "Microsoft.CodeAnalysis.CSharp.dll", "Microsoft.CodeAnalysis.VisualBasic.dll", "Microsoft.CodeAnalysis.Features.dll", @@ -27,15 +26,17 @@ internal class HostWorkspace : Workspace "Microsoft.CodeAnalysis.CSharp.Workspaces.dll", "Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll", "Microsoft.CodeAnalysis.CSharp.Features.dll", - "Microsoft.CodeAnalysis.VisualBasic.Features.dll", - }; + "Microsoft.CodeAnalysis.VisualBasic.Features.dll"); - public HostWorkspace(HostServices host, string? workspaceKind) : base(host, workspaceKind) + public LanguageServerWorkspace(Solution solution, HostServices host, VSCodeAnalyzerLoader vsCodeAnalyzerLoader, ILogger logger, string? workspaceKind) : base(host, workspaceKind) { + SetCurrentSolution(solution); + InitializeDiagnostics(vsCodeAnalyzerLoader, logger); } - internal static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, HostServices hostServices, ILogger logger) + internal static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, HostServices hostServices, ILoggerFactory loggerFactory) { + var logger = loggerFactory.CreateLogger(nameof(LanguageServerWorkspace)); try { // This is weird. Really we don't need a workspace other than it is a useful tool to keep track of LSP changes. @@ -47,15 +48,13 @@ internal static async Task CreateWorkspaceAsync(string solutionPath, // // This is all going to get refactored anyway when we do more project system stuff. using var msbuildWorkspace = MSBuildWorkspace.Create(hostServices); - var solution = await msbuildWorkspace.OpenSolutionAsync(solutionPath); + var solution = await msbuildWorkspace.OpenSolutionAsync(solutionPath).ConfigureAwait(false); - var hostWorkspace = new HostWorkspace(hostServices, WorkspaceKind.Host); - hostWorkspace.SetCurrentSolution(solution); + var vscodeAnalyzerLoader = exportProvider.GetExportedValue(); + var hostWorkspace = new LanguageServerWorkspace(solution, hostServices, vscodeAnalyzerLoader, logger, WorkspaceKind.Host); // SetCurrentSolution does raise workspace events. For now manually register until we figure out how workspaces will work. exportProvider.GetExportedValue().Register(hostWorkspace); - InitializeDiagnostics(hostWorkspace, exportProvider, logger); - return hostWorkspace; } catch (Exception ex) @@ -65,12 +64,12 @@ internal static async Task CreateWorkspaceAsync(string solutionPath, } } - internal static void InitializeDiagnostics(HostWorkspace hostWorkspace, ExportProvider exportProvider, ILogger logger) + internal void InitializeDiagnostics(VSCodeAnalyzerLoader vscodeAnalyzerLoader, ILogger logger) { var baseDirectory = AppContext.BaseDirectory; var references = new List(); var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader(); - foreach (var assemblyName in _hostAnalyzerDlls) + foreach (var assemblyName in s_hostAnalyzerDlls) { var path = Path.Combine(baseDirectory, assemblyName); if (!File.Exists(path)) @@ -79,10 +78,10 @@ internal static void InitializeDiagnostics(HostWorkspace hostWorkspace, ExportPr references.Add(new AnalyzerFileReference(path, analyzerLoader)); } - var newSolution = hostWorkspace.CurrentSolution.WithAnalyzerReferences(references); - hostWorkspace.SetCurrentSolution(newSolution); + var newSolution = this.CurrentSolution.WithAnalyzerReferences(references); + SetCurrentSolution(newSolution); logger.LogDebug($"Loaded host analyzers:{Environment.NewLine}{string.Join(Environment.NewLine, references.Select(r => r.FullPath))}"); - exportProvider.GetExportedValue().InitializeDiagnosticsServices(hostWorkspace); + vscodeAnalyzerLoader.InitializeDiagnosticsServices(this); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 08976151dd39d..be0c5344e7d2a 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -39,9 +39,9 @@ var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); -using (var workspace = await HostWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, logger)) +using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory)) { - var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, logger); + var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost))); await jsonRpc.StartAsync().ConfigureAwait(false); } From 1243847518ffab88fd21dc82c96a5183d95c47ec Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 28 Nov 2022 16:51:18 -0800 Subject: [PATCH 018/261] Include a few more warnings that we have from roslyn --- src/Features/LanguageServer/.editorconfig | 18 +++++++++++++----- .../ExportProviderBuilder.cs | 4 ++-- .../Program.cs | 7 ++----- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Features/LanguageServer/.editorconfig b/src/Features/LanguageServer/.editorconfig index 8764c02269b17..34aa505269325 100644 --- a/src/Features/LanguageServer/.editorconfig +++ b/src/Features/LanguageServer/.editorconfig @@ -180,6 +180,15 @@ dotnet_style_prefer_auto_properties = true:warning dotnet_style_prefer_simplified_boolean_expressions = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:warning +# CA1802: Use literals where appropriate +dotnet_diagnostic.CA1802.severity = warning + +# CA2007: Do not directly await a Task +dotnet_diagnostic.CA2007.severity = warning + +# CA2016: Forward the CancellationToken parameter to methods that take one +dotnet_diagnostic.CA2016.severity = warning + # CSharp code style settings: [*.cs] # Newline settings @@ -252,7 +261,6 @@ csharp_space_between_parentheses = false csharp_space_between_square_brackets = false # Blocks are allowed -csharp_prefer_braces = true:silent csharp_preserve_single_line_blocks = true csharp_preserve_single_line_statements = true csharp_using_directive_placement = outside_namespace:suggestion @@ -309,7 +317,7 @@ dotnet_diagnostic.IDE2003.severity = warning # csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental dotnet_diagnostic.IDE2004.severity = warning -[src/{VisualStudio}/**/*.{cs,vb}] -# CA1822: Make member static -# There is a risk of accidentally breaking an internal API that partners rely on though IVT. -dotnet_code_quality.CA1822.api_surface = private \ No newline at end of file +[{Microsoft.CodeAnalysis.LanguageServer.UnitTests/*.cs}] +# For tests, the ConfigureAwait(true) is good enough. They are already running on a thread pool +# thread where ConfigureAwait(false) does nothing. +dotnet_diagnostic.CA2007.severity = none diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index f8aebd95dc289..806125254e111 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -25,8 +25,8 @@ public static async Task CreateExportProviderAsync() // TODO - we should likely cache the catalog so we don't have to rebuild it every time. var catalog = ComposableCatalog.Create(Resolver.DefaultInstance) - .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly())) - .AddParts(await discovery.CreatePartsAsync(assembliesToDiscover)) + .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()).ConfigureAwait(false)) + .AddParts(await discovery.CreatePartsAsync(assembliesToDiscover).ConfigureAwait(false)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import // Assemble the parts into a valid graph. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index be0c5344e7d2a..e07dcdf1296ec 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -4,12 +4,9 @@ using System.Diagnostics; using Microsoft.Build.Locator; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; -using Microsoft.CodeAnalysis.MSBuild; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -37,9 +34,9 @@ var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); MSBuildLocator.RegisterInstance(msbuildInstances.First()); -var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); +var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync().ConfigureAwait(false); var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); -using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory)) +using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory).ConfigureAwait(false)) { var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost))); From 7037d5d40aaa393841ad55d4834e944100b819fb Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 1 Dec 2022 17:38:03 -0800 Subject: [PATCH 019/261] Add build pipeline that builds extension vsix with server artifacts --- .../Microsoft.CodeAnalysis.LanguageServer.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 8c06ee8dd0572..e4c5e711b36e1 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -5,6 +5,7 @@ net7.0 enable enable + ../../artifacts From 09a235b86640478b21f4836f698fe271974a19bc Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 18 Jan 2023 19:42:34 -0800 Subject: [PATCH 020/261] Publish per platform VSIXs containing the new language servers instead of o#-roslyn --- .../Microsoft.CodeAnalysis.LanguageServer.csproj | 11 +++++++++-- src/Features/LanguageServer/NuGet.config | 1 + src/Features/LanguageServer/global.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index e4c5e711b36e1..555a90cfc15ea 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -1,11 +1,18 @@  - Exe net7.0 enable enable - ../../artifacts + ../../artifacts/bin + + + False + ../../artifacts/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) + ../../artifacts/publish/$(Configuration)/$(TargetFramework)/neutral + + 7.0.0-preview.7.22362.8 + LatestMajor diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config index dfd502e64e5df..7ee7ecade6820 100644 --- a/src/Features/LanguageServer/NuGet.config +++ b/src/Features/LanguageServer/NuGet.config @@ -7,6 +7,7 @@ + diff --git a/src/Features/LanguageServer/global.json b/src/Features/LanguageServer/global.json index 52534e2d8a98e..08585a2b3be24 100644 --- a/src/Features/LanguageServer/global.json +++ b/src/Features/LanguageServer/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "7.0.100-rc.2.22477.23" + "version": "7.0.100" } } \ No newline at end of file From 13c77dfd55a778e359e3a8e017e45cec712eec90 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 23 Jan 2023 16:17:40 -0800 Subject: [PATCH 021/261] Feedback --- .../Microsoft.CodeAnalysis.LanguageServer.csproj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 555a90cfc15ea..69e59a5fd80f5 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -4,12 +4,13 @@ net7.0 enable enable - ../../artifacts/bin + ../../artifacts + $(ArtifactsPath)/bin False - ../../artifacts/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) - ../../artifacts/publish/$(Configuration)/$(TargetFramework)/neutral + $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) + $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/neutral 7.0.0-preview.7.22362.8 LatestMajor From 82ff670b8d1ca7cfb3d9533af78b31880ee42024 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 24 Jan 2023 18:00:03 -0800 Subject: [PATCH 022/261] Implement client side command for code lens resolution --- src/Features/LanguageServer/Directory.Packages.props | 4 ++-- src/Features/LanguageServer/NuGet.config | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index e8f904ab561db..a48caaf851b48 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,7 +2,7 @@ 1.5.5 - 4.5.0-2.22577.2 + 4.6.0-dev $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) @@ -15,6 +15,6 @@ 17.2.41 17.5.20-preview 2.9.112 - 2.14.17-alpha + 2.14.20 \ No newline at end of file diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config index 7ee7ecade6820..618771e844710 100644 --- a/src/Features/LanguageServer/NuGet.config +++ b/src/Features/LanguageServer/NuGet.config @@ -8,6 +8,7 @@ + From c3d599401de155d86322f6fd1d65c06b302ddfdd Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 25 Jan 2023 00:38:47 -0800 Subject: [PATCH 023/261] Improve logging by 1. Splitting out trace logging from the vscode client from our extension logs 2. Using the lsp log message method to send log messages from server to client and implementing a fallback when LSP has not initialized --- .../HostLspLogger.cs | 29 -------- .../LanguageServer/LanguageServerHost.cs | 27 ++++++-- .../Logging/AggregateLogger.cs | 67 +++++++++++++++++++ .../Logging/AggregateLoggerProvider.cs | 29 ++++++++ .../Logging/LspServiceLogger.cs | 32 +++++++++ .../Program.cs | 52 ++++++++++---- 6 files changed, 190 insertions(+), 46 deletions(-) delete mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs deleted file mode 100644 index ec7cd4070d3af..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostLspLogger.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Extensions.Logging; - -namespace Microsoft.CodeAnalysis.LanguageServer; - -internal sealed class HostLspLogger : ILspServiceLogger -{ - private readonly ILogger _logger; - - public HostLspLogger(ILogger logger) - { - _logger = logger; - } - - public void LogEndContext(string message, params object[] @params) => _logger.LogTrace($"[{DateTime.UtcNow:hh:mm:ss.fff}][End]{message}", @params); - - public void LogError(string message, params object[] @params) => _logger.LogError(message, @params); - - public void LogException(Exception exception, string? message = null, params object[] @params) => _logger.LogError(exception, message, @params); - - public void LogInformation(string message, params object[] @params) => _logger.LogInformation(message, @params); - - public void LogStartContext(string message, params object[] @params) => _logger.LogTrace($"[{DateTime.UtcNow:hh:mm:ss.fff}][Start]{message}", @params); - - public void LogWarning(string message, params object[] @params) => _logger.LogWarning(message, @params); -} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index 931bb5acbc3de..e9f180829ae1f 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; +using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.CommonLanguageServerProtocol.Framework; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -12,16 +13,23 @@ namespace Microsoft.CodeAnalysis.LanguageServer; +#pragma warning disable CA1001 // The JsonRpc instance is disposed of by the AbstractLanguageServer during shutdown internal sealed class LanguageServerHost +#pragma warning restore CA1001 // The JsonRpc instance is disposed of by the AbstractLanguageServer during shutdown { - private readonly JsonRpc _jsonRpc; + /// + /// A static reference to the server instance. + /// Used by loggers to determine if they can send log messages via LSP + /// or if they need to use a fallback mechanism. + /// + internal static LanguageServerHost? Instance { get; private set; } + private readonly ILogger _logger; private readonly AbstractLanguageServer _roslynLanguageServer; + private readonly JsonRpc _jsonRpc; public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, HostServices hostServices, ILogger logger) { - _logger = logger; - var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, new JsonMessageFormatter()); // If there is a jsonrpc disconnect or server shutdown, that is handled by the AbstractLanguageServer. No need to do anything here. @@ -32,7 +40,9 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvide var roslynLspFactory = exportProvider.GetExportedValue(); var capabilitiesProvider = new ServerCapabilitiesProvider(exportProvider.GetExportedValue()); - var lspLogger = new HostLspLogger(logger); + + _logger = logger; + var lspLogger = new LspServiceLogger(_logger); _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices); } @@ -40,7 +50,16 @@ public async Task StartAsync() { _logger.LogInformation("Starting server..."); _jsonRpc.StartListening(); + + // Now that the server is started, update the our instance reference + Instance = this; + await _jsonRpc.Completion.ConfigureAwait(false); await _roslynLanguageServer.WaitForExitAsync().ConfigureAwait(false); } + + public Task NotifyAsync(string targetName, object? argument) + { + return _jsonRpc.NotifyAsync(targetName, argument); + } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs new file mode 100644 index 0000000000000..3d93921694290 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using StreamJsonRpc; + +namespace Microsoft.CodeAnalysis.LanguageServer.Logging; + +/// +/// Implements an ILogger that seamlessly switches from a fallback logger +/// to LSP log messages as soon as the server initializes. +/// +internal sealed class AggregateLogger : ILogger +{ + private readonly string _categoryName; + private readonly ILogger _fallbackLogger; + + public AggregateLogger(string categoryName, ILoggerFactory fallbackLoggerFactory) + { + _categoryName = categoryName; + _fallbackLogger = fallbackLoggerFactory.CreateLogger(categoryName); + } + + public IDisposable BeginScope(TState state) + { + throw new NotImplementedException(); + } + + public bool IsEnabled(LogLevel logLevel) + { + return true; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + var server = LanguageServerHost.Instance; + if (server == null) + { + // If the language server has not been initialized yet, log using the fallback logger. + _fallbackLogger.Log(logLevel, eventId, state, exception, formatter); + return; + } + + var message = formatter(state, exception); + if (message != null && logLevel != LogLevel.None) + { + message = $"[{_categoryName}]{message}"; + var _ = server.NotifyAsync(Methods.WindowLogMessageName, new LogMessageParams() + { + Message = message, + MessageType = logLevel switch + { + LogLevel.Trace => MessageType.Log, + LogLevel.Debug => MessageType.Log, + LogLevel.Information => MessageType.Info, + LogLevel.Warning => MessageType.Warning, + LogLevel.Error => MessageType.Error, + LogLevel.Critical => MessageType.Error, + _ => throw new InvalidOperationException($"Unexpected logLevel argument {logLevel}"), + } + }); + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs new file mode 100644 index 0000000000000..2ce37ba983eb6 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Concurrent; +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer.Logging; +internal class AggregateLoggerProvider : ILoggerProvider +{ + private readonly ILoggerFactory _fallbackLoggerFactory; + private readonly ConcurrentDictionary _loggers = new(StringComparer.OrdinalIgnoreCase); + + public AggregateLoggerProvider(ILoggerFactory fallbackLoggerFactory) + { + _fallbackLoggerFactory = fallbackLoggerFactory; + } + + public ILogger CreateLogger(string categoryName) + { + return _loggers.GetOrAdd(categoryName, new AggregateLogger(categoryName, _fallbackLoggerFactory)); + } + + public void Dispose() + { + _loggers.Clear(); + _fallbackLoggerFactory.Dispose(); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs new file mode 100644 index 0000000000000..af67b3152b17e --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer.Logging; + +/// +/// Implements by sending LSP log messages back to the client. +/// +internal sealed class LspServiceLogger : ILspServiceLogger +{ + private readonly ILogger _hostLogger; + + public LspServiceLogger(ILogger hostLogger) + { + _hostLogger = hostLogger; + } + + public void LogEndContext(string message, params object[] @params) => _hostLogger.LogDebug($"[{DateTime.UtcNow:hh:mm:ss.fff}][End]{message}", @params); + + public void LogError(string message, params object[] @params) => _hostLogger.LogError(message, @params); + + public void LogException(Exception exception, string? message = null, params object[] @params) => _hostLogger.LogError(exception, message, @params); + + public void LogInformation(string message, params object[] @params) => _hostLogger.LogDebug(message, @params); + + public void LogStartContext(string message, params object[] @params) => _hostLogger.LogDebug($"[{DateTime.UtcNow:hh:mm:ss.fff}][Start]{message}", @params); + + public void LogWarning(string message, params object[] @params) => _hostLogger.LogWarning(message, @params); +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index e07dcdf1296ec..b93c709e98ef8 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -7,23 +7,28 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; +using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; -// TODO - Decide how and where we're logging. For now just logging stderr (vscode reads stdout for LSP messages). -// 1. File logs for feedback -// 2. Logs to vscode output window. -// 3. Telemetry -// Also decide how we configure logging (env variables, extension settings, etc.) -// https://github.com/microsoft/vscode-csharp-next/issues/12 +var minimumLogLevel = GetLogLevel(args); + +// Before we initialize the LSP server we can't send LSP log messages. +// Create a console logger as a fallback to use before the LSP server starts. using var loggerFactory = LoggerFactory.Create(builder => { - builder.SetMinimumLevel(LogLevel.Trace); - builder.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace); + builder.SetMinimumLevel(minimumLogLevel); + builder.AddProvider(new AggregateLoggerProvider(fallbackLoggerFactory: + // Add a console logger as a fallback for when the LSP server has not finished initializing. + LoggerFactory.Create(builder => + { + builder.SetMinimumLevel(minimumLogLevel); + builder.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace); + }) + )); }); -var logger = loggerFactory.CreateLogger(); LaunchDebuggerIfEnabled(args); @@ -36,20 +41,41 @@ var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync().ConfigureAwait(false); var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); + using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory).ConfigureAwait(false)) { - var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost))); + var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost))); - await jsonRpc.StartAsync().ConfigureAwait(false); + await server.StartAsync().ConfigureAwait(false); } +loggerFactory.Dispose(); + return; -void LaunchDebuggerIfEnabled(string[] args) +static LogLevel GetLogLevel(string[] args) +{ + var logLevelIndex = Array.IndexOf(args, "--logLevel") + 1; + if (logLevelIndex > 0) + { + var level = args[logLevelIndex]; + return level switch + { + "off" => LogLevel.None, + "minimal" => LogLevel.Information, + "messages" => LogLevel.Debug, + "verbose" => LogLevel.Trace, + _ => throw new InvalidOperationException($"Unexpected logLevel argument {level}"), + }; + } + + return LogLevel.Information; +} + +static void LaunchDebuggerIfEnabled(string[] args) { if (args.Contains("--debug") && !Debugger.IsAttached) { - logger.LogInformation("Launching debugger..."); _ = Debugger.Launch(); } } From a4ec5082ee71c5adc81597c1a59c6e2330ac315f Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 31 Jan 2023 16:31:12 -0800 Subject: [PATCH 024/261] Review feedback --- .../{AggregateLogger.cs => LspLogMessageLogger.cs} | 4 ++-- ...teLoggerProvider.cs => LspLogMessageLoggerProvider.cs} | 8 ++++---- .../Logging/LspServiceLogger.cs | 3 +++ .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 3 ++- 4 files changed, 11 insertions(+), 7 deletions(-) rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/{AggregateLogger.cs => LspLogMessageLogger.cs} (94%) rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/{AggregateLoggerProvider.cs => LspLogMessageLoggerProvider.cs} (63%) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs similarity index 94% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs index 3d93921694290..3d4cfe2a9601d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs @@ -13,12 +13,12 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Logging; /// Implements an ILogger that seamlessly switches from a fallback logger /// to LSP log messages as soon as the server initializes. /// -internal sealed class AggregateLogger : ILogger +internal sealed class LspLogMessageLogger : ILogger { private readonly string _categoryName; private readonly ILogger _fallbackLogger; - public AggregateLogger(string categoryName, ILoggerFactory fallbackLoggerFactory) + public LspLogMessageLogger(string categoryName, ILoggerFactory fallbackLoggerFactory) { _categoryName = categoryName; _fallbackLogger = fallbackLoggerFactory.CreateLogger(categoryName); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLoggerProvider.cs similarity index 63% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLoggerProvider.cs index 2ce37ba983eb6..1f216c21c4550 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/AggregateLoggerProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLoggerProvider.cs @@ -6,19 +6,19 @@ using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.LanguageServer.Logging; -internal class AggregateLoggerProvider : ILoggerProvider +internal class LspLogMessageLoggerProvider : ILoggerProvider { private readonly ILoggerFactory _fallbackLoggerFactory; - private readonly ConcurrentDictionary _loggers = new(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary _loggers = new(StringComparer.OrdinalIgnoreCase); - public AggregateLoggerProvider(ILoggerFactory fallbackLoggerFactory) + public LspLogMessageLoggerProvider(ILoggerFactory fallbackLoggerFactory) { _fallbackLoggerFactory = fallbackLoggerFactory; } public ILogger CreateLogger(string categoryName) { - return _loggers.GetOrAdd(categoryName, new AggregateLogger(categoryName, _fallbackLoggerFactory)); + return _loggers.GetOrAdd(categoryName, new LspLogMessageLogger(categoryName, _fallbackLoggerFactory)); } public void Dispose() diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs index af67b3152b17e..5da7012ea5e5d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspServiceLogger.cs @@ -24,6 +24,9 @@ public LspServiceLogger(ILogger hostLogger) public void LogException(Exception exception, string? message = null, params object[] @params) => _hostLogger.LogError(exception, message, @params); + /// + /// TODO - This should call LogInformation, however we need to introduce a LogDebug call in clasp first. + /// public void LogInformation(string message, params object[] @params) => _hostLogger.LogDebug(message, @params); public void LogStartContext(string message, params object[] @params) => _hostLogger.LogDebug($"[{DateTime.UtcNow:hh:mm:ss.fff}][Start]{message}", @params); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index b93c709e98ef8..791a59e33043e 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -20,7 +20,7 @@ using var loggerFactory = LoggerFactory.Create(builder => { builder.SetMinimumLevel(minimumLogLevel); - builder.AddProvider(new AggregateLoggerProvider(fallbackLoggerFactory: + builder.AddProvider(new LspLogMessageLoggerProvider(fallbackLoggerFactory: // Add a console logger as a fallback for when the LSP server has not finished initializing. LoggerFactory.Create(builder => { @@ -58,6 +58,7 @@ static LogLevel GetLogLevel(string[] args) var logLevelIndex = Array.IndexOf(args, "--logLevel") + 1; if (logLevelIndex > 0) { + // Map VSCode log level to the LogLevel we can use with ILogger APIs. var level = args[logLevelIndex]; return level switch { From 838316348f2bb082f5b3d9d02b43dc18a0df7a5b Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Feb 2023 12:08:48 -0800 Subject: [PATCH 025/261] Use real package versions --- src/Features/LanguageServer/Directory.Packages.props | 4 +--- .../Microsoft.CodeAnalysis.LanguageServer.csproj | 2 -- src/Features/LanguageServer/NuGet.config | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index a48caaf851b48..3d294ca044ddc 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,11 +2,9 @@ 1.5.5 - 4.6.0-dev + 4.6.0-2.23101.21 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) - $(MicrosoftCodeAnalysisVersion) - $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) 6.0.0 diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 69e59a5fd80f5..bdad50eae96b3 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -19,8 +19,6 @@ - - diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config index 618771e844710..7ee7ecade6820 100644 --- a/src/Features/LanguageServer/NuGet.config +++ b/src/Features/LanguageServer/NuGet.config @@ -8,7 +8,6 @@ - From 3ffc30bbc8e287948ec1a9b5c9e0b96465c67c8e Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 10 Jan 2023 12:45:05 -0800 Subject: [PATCH 026/261] Suppress CA1848 and CA2254 while we're still ignoring them --- src/Features/LanguageServer/.editorconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Features/LanguageServer/.editorconfig b/src/Features/LanguageServer/.editorconfig index 34aa505269325..821d99ae91d6e 100644 --- a/src/Features/LanguageServer/.editorconfig +++ b/src/Features/LanguageServer/.editorconfig @@ -189,6 +189,12 @@ dotnet_diagnostic.CA2007.severity = warning # CA2016: Forward the CancellationToken parameter to methods that take one dotnet_diagnostic.CA2016.severity = warning +# CA1848: Use LoggerMessage delegates when calling ILogger methods +dotnet_diagnostic.CA1848.severity = none + +# CA2254: Logging message template should not vary between calls +dotnet_diagnostic.CA2254.severity = none + # CSharp code style settings: [*.cs] # Newline settings From 716d246bab5af17de2d250b25a3a21118c3038e4 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 31 Jan 2023 16:29:46 -0800 Subject: [PATCH 027/261] Add Directory.Packages.props to the solution items Since we've already got the Build.props, it seems appropriate. --- .../LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln index c2f769134cf72..0ca8a563acdc1 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props NuGet.config = NuGet.config EndProjectSection EndProject From 515f0a39cec217b12bf84659951175622b1e564d Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Mon, 9 Jan 2023 18:04:01 -0800 Subject: [PATCH 028/261] Add some blank lines to make reading the packages file easier --- src/Features/LanguageServer/Directory.Packages.props | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 3d294ca044ddc..13626e6f821f3 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -2,17 +2,20 @@ 1.5.5 + 4.6.0-2.23101.21 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) + 6.0.0 6.0.2 $(MicrosoftExtensionsLoggingVersion) + 17.2.41 17.5.20-preview 2.9.112 2.14.20 - \ No newline at end of file + From 9f86d6818cbeb6ad4d21538a2cf578f408b1f401 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 10 Jan 2023 11:53:56 -0800 Subject: [PATCH 029/261] Split apart the WaitForExitAsync() for the language server This way we can start while we're starting other stuff async. --- .../AbstractLanguageServerHostTests.cs | 4 +++- .../LanguageServer/LanguageServerHost.cs | 5 ++++- .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs index 9ee2fd8448eb0..7a82164da6564 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -59,7 +59,9 @@ private TestLspServer(ExportProvider exportProvider, ILogger logger) // This task completes when the server shuts down. We store it so that we can wait for completion // when we dispose of the test server. - _languageServerHostCompletionTask = _languageServerHost.StartAsync(); + _languageServerHost.Start(); + + _languageServerHostCompletionTask = _languageServerHost.WaitForExitAsync(); } public async Task ExecuteRequestAsync(string methodName, RequestType request, CancellationToken cancellationToken) where RequestType : class diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index e9f180829ae1f..4c28ed91462e2 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -46,14 +46,17 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvide _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices); } - public async Task StartAsync() + public void Start() { _logger.LogInformation("Starting server..."); _jsonRpc.StartListening(); // Now that the server is started, update the our instance reference Instance = this; + } + public async Task WaitForExitAsync() + { await _jsonRpc.Completion.ConfigureAwait(false); await _roslynLanguageServer.WaitForExitAsync().ConfigureAwait(false); } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 791a59e33043e..88aa03443b399 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -46,7 +46,8 @@ { var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost))); - await server.StartAsync().ConfigureAwait(false); + server.Start(); + await server.WaitForExitAsync().ConfigureAwait(false); } loggerFactory.Dispose(); From b8c0ccf51fedcc325549ff51f710b44b8b89bbd6 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Wed, 18 Jan 2023 17:50:47 -0800 Subject: [PATCH 030/261] Use MEF a bit more --- .../AbstractLanguageServerHostTests.cs | 5 +-- .../ExportProviderBuilder.cs | 5 +-- .../HostServicesProvider.cs | 25 ++++++++++++ .../LanguageServer/LanguageServerHost.cs | 8 ++-- .../Logging/LspLogMessageLogger.cs | 1 + .../Logging/ServerLoggerFactory.cs | 40 +++++++++++++++++++ .../Program.cs | 11 ++++- 7 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs index 7a82164da6564..fa8aba266cbfe 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -47,8 +47,7 @@ public static async Task CreateAsync(ClientCapabilities clientCap private TestLspServer(ExportProvider exportProvider, ILogger logger) { var (clientStream, serverStream) = FullDuplexStream.CreatePair(); - var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); - _languageServerHost = new LanguageServerHost(serverStream, serverStream, exportProvider, hostServices, logger); + _languageServerHost = new LanguageServerHost(serverStream, serverStream, exportProvider, logger); _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, new JsonMessageFormatter())) { diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 806125254e111..316dfed0c86b3 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Immutable; -using System.Diagnostics.Contracts; using System.Reflection; +using Microsoft.CodeAnalysis.LanguageServer.Logging; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.LanguageServer; @@ -42,7 +42,6 @@ public static async Task CreateExportProviderAsync() // You can create as many of these as you want, but typically an app needs just one. var exportProvider = exportProviderFactory.CreateExportProvider(); - // Obtain our first exported value return exportProvider; } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs new file mode 100644 index 0000000000000..12578596178d6 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.LanguageServer; + +/// +/// A simple type to provide a single copy of for the MEF composition. +/// +[Export(typeof(HostServicesProvider)), Shared] +internal class HostServicesProvider +{ + public HostServices HostServices { get; } + + [ImportingConstructor] + public HostServicesProvider(ExportProvider exportProvider) + { + HostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index 4c28ed91462e2..27a130b9f043a 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -2,16 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServer.Handler; -using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.CommonLanguageServerProtocol.Framework; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; using StreamJsonRpc; -namespace Microsoft.CodeAnalysis.LanguageServer; +namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; #pragma warning disable CA1001 // The JsonRpc instance is disposed of by the AbstractLanguageServer during shutdown internal sealed class LanguageServerHost @@ -28,7 +26,7 @@ internal sealed class LanguageServerHost private readonly AbstractLanguageServer _roslynLanguageServer; private readonly JsonRpc _jsonRpc; - public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, HostServices hostServices, ILogger logger) + public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, ILogger logger) { var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, new JsonMessageFormatter()); @@ -43,6 +41,8 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvide _logger = logger; var lspLogger = new LspServiceLogger(_logger); + + var hostServices = exportProvider.GetExportedValue().HostServices; _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices); } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs index 3d4cfe2a9601d..b3390b7e142e6 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Composition; +using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.LanguageServer.Protocol; using StreamJsonRpc; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs new file mode 100644 index 0000000000000..e46f1ea0e61de --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using Microsoft.Extensions.Logging; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.Logging; + +[Export(typeof(ILoggerFactory))] +[Export(typeof(ServerLoggerFactory))] +[Shared] +internal class ServerLoggerFactory : ILoggerFactory +{ + private ILoggerFactory? _loggerFactory; + + public void SetFactory(ILoggerFactory loggerFactory) + { + Contract.ThrowIfTrue(_loggerFactory is not null); + _loggerFactory = loggerFactory; + } + + void ILoggerFactory.AddProvider(ILoggerProvider provider) + { + Contract.ThrowIfNull(_loggerFactory); + _loggerFactory.AddProvider(provider); + } + + ILogger ILoggerFactory.CreateLogger(string categoryName) + { + Contract.ThrowIfNull(_loggerFactory); + return _loggerFactory.CreateLogger(categoryName); + } + + void IDisposable.Dispose() + { + _loggerFactory?.Dispose(); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 88aa03443b399..dceef8fbf7674 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; +using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -40,16 +41,22 @@ MSBuildLocator.RegisterInstance(msbuildInstances.First()); var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync().ConfigureAwait(false); -var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); + +// Immediately set the logger factory, so that way it'll be available for the rest of the composition +exportProvider.GetExportedValue().SetFactory(loggerFactory); + +var hostServices = exportProvider.GetExportedValue().HostServices; using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory).ConfigureAwait(false)) { - var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost))); + var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); server.Start(); await server.WaitForExitAsync().ConfigureAwait(false); } +// Dispose of our container, so parts can cleanly shut themselves down +exportProvider.Dispose(); loggerFactory.Dispose(); return; From 8b83ac76ec2d3c18f3ec24e5ce9a98af711cdc22 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Wed, 1 Feb 2023 11:56:52 -0800 Subject: [PATCH 031/261] Silence some analysis warnings --- .../AbstractLanguageServerHostTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs index fa8aba266cbfe..5f2320b691ff4 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; public abstract class AbstractLanguageServerHostTests { - protected readonly ILogger TestOutputLogger; + protected ILogger TestOutputLogger { get; } protected AbstractLanguageServerHostTests(ITestOutputHelper testOutputHelper) { @@ -63,9 +63,9 @@ private TestLspServer(ExportProvider exportProvider, ILogger logger) _languageServerHostCompletionTask = _languageServerHost.WaitForExitAsync(); } - public async Task ExecuteRequestAsync(string methodName, RequestType request, CancellationToken cancellationToken) where RequestType : class + public async Task ExecuteRequestAsync(string methodName, TRequestType request, CancellationToken cancellationToken) where TRequestType : class { - var result = await _clientRpc.InvokeWithParameterObjectAsync(methodName, request, cancellationToken: cancellationToken).ConfigureAwait(false); + var result = await _clientRpc.InvokeWithParameterObjectAsync(methodName, request, cancellationToken: cancellationToken).ConfigureAwait(false); return result; } From dc72e9a020ef8c953ad30f0a253fb2f4220a255b Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Wed, 18 Jan 2023 18:37:22 -0800 Subject: [PATCH 032/261] Implement a basic project system atop our core project system support Instead of using MSBuildWorkspace to load the solution once, this uses the underlying MSBuildWorkspace support to and then feeds it into ProjectSystemProjects; this means we're able to do reloads that can update existing state. This also implements a trivial file watcher to look for file changes so we can also reload the projects or file contents accordingly. A few things it doesn't do yet: 1. Support unloading of projects. 2. The ability to load a solution/project dynamically; we're still relying on that being set from the launch. --- .../LanguageServer/Directory.Packages.props | 1 + .../HostWorkspace/FileChangeWatcher.cs | 153 +++++++++++++++ .../LanguageServerProjectSystem.cs | 181 ++++++++++++++++++ .../HostWorkspace/LanguageServerWorkspace.cs | 75 +------- .../HostWorkspace/LoadedProject.cs | 168 ++++++++++++++++ .../HostWorkspace/MetadataService.cs | 67 +++++++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 1 + .../Program.cs | 25 ++- 8 files changed, 588 insertions(+), 83 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 13626e6f821f3..82755fcab37b8 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -1,6 +1,7 @@ + 17.4.0 1.5.5 4.6.0-2.23101.21 diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs new file mode 100644 index 0000000000000..0de3ff2197def --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Composition; +using Microsoft.CodeAnalysis.ProjectSystem; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +[Export(typeof(IFileChangeWatcher)), Shared] +internal sealed class FileChangeWatcher : IFileChangeWatcher +{ + public IFileChangeContext CreateContext(params WatchedDirectory[] watchedDirectories) + { + return new FileChangeContext(watchedDirectories.ToImmutableArray()); + } + + private class FileChangeContext : IFileChangeContext + { + private readonly ImmutableArray _watchedDirectories; + + /// + /// The directory watchers for the . + /// + private readonly ImmutableArray _directoryFileSystemWatchers; + private readonly ConcurrentSet _individualWatchedFiles = new ConcurrentSet(); + + public FileChangeContext(ImmutableArray watchedDirectories) + { + _watchedDirectories = watchedDirectories; + var builder = ImmutableArray.CreateBuilder(watchedDirectories.Length); + + foreach (var watchedDirectory in watchedDirectories) + { + var watcher = new FileSystemWatcher(watchedDirectory.Path); + watcher.IncludeSubdirectories = true; + + if (watchedDirectory.ExtensionFilter != null) + watcher.Filter = '*' + watchedDirectory.ExtensionFilter; + + watcher.Changed += RaiseEvent; + watcher.Created += RaiseEvent; + watcher.Deleted += RaiseEvent; + watcher.Renamed += RaiseEvent; + + watcher.EnableRaisingEvents = true; + + builder.Add(watcher); + } + + _directoryFileSystemWatchers = builder.ToImmutable(); + } + + public event EventHandler? FileChanged; + + public IWatchedFile EnqueueWatchingFile(string filePath) + { + // If this path is already covered by one of our directory watchers, nothing further to do + foreach (var watchedDirectory in _watchedDirectories) + { + if (filePath.StartsWith(watchedDirectory.Path, StringComparison.Ordinal)) + { + // If ExtensionFilter is null, then we're watching for all files in the directory so the prior check + // of the directory containment was sufficient. If it isn't null, then we have to check the extension + // matches. + if (watchedDirectory.ExtensionFilter == null || filePath.EndsWith(watchedDirectory.ExtensionFilter, StringComparison.Ordinal)) + { + return NoOpWatchedFile.Instance; + } + } + } + + var individualWatchedFile = new IndividualWatchedFile(filePath, this); + _individualWatchedFiles.Add(individualWatchedFile); + return individualWatchedFile; + } + + private void RaiseEvent(object sender, FileSystemEventArgs e) + { + FileChanged?.Invoke(this, e.FullPath); + } + + public void Dispose() + { + foreach (var directoryWatcher in _directoryFileSystemWatchers) + directoryWatcher.Dispose(); + } + + /// + /// When a FileChangeWatcher already has a watch on a directory, a request to watch a specific file is a no-op. In that case, we return this token, + /// which when disposed also does nothing. + /// + internal sealed class NoOpWatchedFile : IWatchedFile + { + public static readonly IWatchedFile Instance = new NoOpWatchedFile(); + + private NoOpWatchedFile() + { + } + + public void Dispose() + { + } + } + + private class IndividualWatchedFile : IWatchedFile + { + private readonly FileChangeContext _context; + private readonly FileSystemWatcher? _watcher; + + public IndividualWatchedFile(string filePath, FileChangeContext context) + { + _context = context; + + // We always must create a watch on an entire directory, so create that, filtered to the single file name + var directoryPath = Path.GetDirectoryName(filePath)!; + + // TODO: support missing directories properly + if (Directory.Exists(directoryPath)) + { + _watcher = new FileSystemWatcher(directoryPath, Path.GetFileName(filePath)); + _watcher.IncludeSubdirectories = false; + + _watcher.Changed += _context.RaiseEvent; + _watcher.Created += _context.RaiseEvent; + _watcher.Deleted += _context.RaiseEvent; + _watcher.Renamed += _context.RaiseEvent; + + _watcher.EnableRaisingEvents = true; + } + else + { + _watcher = null; + } + } + + public void Dispose() + { + if (_context._individualWatchedFiles.Remove(this)) + { + Contract.ThrowIfNull(_watcher); + _watcher.Changed -= _context.RaiseEvent; + _watcher.Created -= _context.RaiseEvent; + _watcher.Deleted -= _context.RaiseEvent; + _watcher.Renamed -= _context.RaiseEvent; + _watcher.Dispose(); + } + } + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs new file mode 100644 index 0000000000000..b55fa1b2e493b --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -0,0 +1,181 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Concurrent; +using System.Collections.Immutable; +using System.Composition; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; +using Microsoft.CodeAnalysis.MSBuild; +using Microsoft.CodeAnalysis.MSBuild.Build; +using Microsoft.CodeAnalysis.ProjectSystem; +using Microsoft.CodeAnalysis.Shared.TestHooks; +using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Composition; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +[Export(typeof(LanguageServerProjectSystem)), Shared] +internal sealed class LanguageServerProjectSystem +{ + private readonly ILogger _logger; + private readonly ProjectSystemProjectFactory _projectSystemProjectFactory; + private readonly ProjectFileLoaderRegistry _projectFileLoaderRegistry; + private readonly AsyncBatchingWorkQueue _projectsToLoadAndReload; + private readonly ProjectSystemHostInfo _projectHostInfo; + private readonly IFileChangeWatcher _fileChangeWatcher; + + /// + /// The list of loaded projects in the workspace, keyed by project file path. The outer dictionary is a concurrent dictionary since we may be loading + /// multiple projects at once; the key is a single List we just have a single thread processing any given project file. + /// + private readonly ConcurrentDictionary> _loadedProjects = new(); + + [ImportingConstructor] + public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VSCodeAnalyzerLoader analyzerLoader, IFileChangeWatcher fileChangeWatcher, ILoggerFactory loggerFactory, IAsynchronousOperationListenerProvider listenerProvider) + { + _logger = loggerFactory.CreateLogger(nameof(LanguageServerProjectSystem)); + Workspace = new LanguageServerWorkspace(hostServicesProvider.HostServices); + _projectSystemProjectFactory = new ProjectSystemProjectFactory(Workspace, new FileChangeWatcher(), static _ => { }, _ => { }); + + analyzerLoader.InitializeDiagnosticsServices(Workspace); + + // TODO: remove the DiagnosticReporter that's coupled to the Workspace here + _projectFileLoaderRegistry = new ProjectFileLoaderRegistry(Workspace.Services.SolutionServices, new DiagnosticReporter(Workspace)); + + _projectsToLoadAndReload = new AsyncBatchingWorkQueue( + TimeSpan.FromMilliseconds(100), + LoadOrReloadProjectsAsync, + listenerProvider.GetListener(FeatureAttribute.Workspace), + CancellationToken.None); // TODO: do we need to introduce a shutdown cancellation token for this? + + // TODO: fill this out + _projectHostInfo = new ProjectSystemHostInfo( + DynamicFileInfoProviders: ImmutableArray>.Empty, + null!, + null!); + _fileChangeWatcher = fileChangeWatcher; + } + + public Workspace Workspace { get; } + + public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray analyzerPaths) + { + var references = new List(); + var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader(); + + foreach (var analyzerPath in analyzerPaths) + { + if (File.Exists(analyzerPath)) + { + _logger.LogWarning($"Solution-level analyzer at {analyzerPath} added to workspace."); + references.Add(new AnalyzerFileReference(analyzerPath, analyzerLoader)); + } + else + { + _logger.LogWarning($"Solution-level analyzer at {analyzerPath} could not be found."); + } + } + + await _projectSystemProjectFactory.ApplyChangeToWorkspaceAsync(w => w.SetCurrentSolution(s => s.WithAnalyzerReferences(references), WorkspaceChangeKind.SolutionChanged)).ConfigureAwait(false); + } + + public void OpenSolution(string solutionFilePath) + { + _logger.LogInformation($"Opening solution {solutionFilePath}"); + + var solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(solutionFilePath); + + foreach (var project in solutionFile.ProjectsInOrder) + { + if (project.ProjectType == Microsoft.Build.Construction.SolutionProjectType.SolutionFolder) + { + continue; + } + + _projectsToLoadAndReload.AddWork(project.AbsolutePath); + } + } + + private async ValueTask LoadOrReloadProjectsAsync(ImmutableSegmentedList projectPathsToLoadOrReload, CancellationToken disposalToken) + { + var stopwatch = Stopwatch.StartNew(); + + // TODO: support configuration switching + var projectBuildManager = new ProjectBuildManager(additionalGlobalProperties: ImmutableDictionary.Empty); + + projectBuildManager.StartBatchBuild(); + + try + { + var tasks = new List(); + + foreach (var projectPathToLoadOrReload in projectPathsToLoadOrReload) + { + tasks.Add(Task.Run(() => LoadOrReloadProjectAsync(projectPathToLoadOrReload, projectBuildManager, disposalToken), disposalToken)); + } + + await Task.WhenAll(tasks).ConfigureAwait(false); + } + finally + { + projectBuildManager.EndBatchBuild(); + + _logger.LogInformation($"Completed (re)load of all projects in {stopwatch.Elapsed}"); + } + } + + private async Task LoadOrReloadProjectAsync(string projectPath, ProjectBuildManager projectBuildManager, CancellationToken disposalToken) + { + try + { + if (_projectFileLoaderRegistry.TryGetLoaderFromProjectPath(projectPath, out var loader)) + { + var loadedFile = await loader.LoadProjectFileAsync(projectPath, projectBuildManager, disposalToken).ConfigureAwait(false); + var loadedProjectInfos = await loadedFile.GetProjectFileInfosAsync(disposalToken).ConfigureAwait(false); + + var existingProjects = _loadedProjects.GetOrAdd(projectPath, static _ => new List()); + + foreach (var loadedProjectInfo in loadedProjectInfos) + { + // If we already have the project, just update it + var existingProject = existingProjects.Find(p => p.GetTargetFramework() == loadedProjectInfo.TargetFramework); + + if (existingProject != null) + { + await existingProject.UpdateWithNewProjectInfoAsync(loadedProjectInfo).ConfigureAwait(false); + } + else + { + var projectSystemName = $"{projectPath} (${loadedProjectInfo.TargetFramework})"; + var projectCreationInfo = new ProjectSystemProjectCreationInfo { AssemblyName = projectSystemName, FilePath = projectPath }; + + var projectSystemProject = await _projectSystemProjectFactory.CreateAndAddToWorkspaceAsync( + projectSystemName, + loadedProjectInfo.Language, + projectCreationInfo, + _projectHostInfo).ConfigureAwait(false); + + var loadedProject = new LoadedProject(projectSystemProject, Workspace.Services.SolutionServices, _fileChangeWatcher); + loadedProject.NeedsReload += (_, _) => _projectsToLoadAndReload.AddWork(projectPath); + existingProjects.Add(loadedProject); + + await loadedProject.UpdateWithNewProjectInfoAsync(loadedProjectInfo).ConfigureAwait(false); + } + } + } + + _logger.LogInformation($"Successfully completed load of {projectPath}"); + } + catch (Exception e) + { + _logger.LogError(e, $"Exception thrown while loading {projectPath}"); + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs index e5bb7e3b17104..fdfdae5e40837 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs @@ -3,85 +3,12 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; -using Microsoft.CodeAnalysis.MSBuild; -using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; internal class LanguageServerWorkspace : Workspace { - /// - /// Set of assemblies to look for host installed analyzers. - /// Similar to https://github.com/dotnet/roslyn/blob/9fee6f5461baae5152c956c3c3024ca15b85feb9/src/VisualStudio/Setup/source.extension.vsixmanifest#L51 - /// except only include dlls applicable to VSCode. - /// - private static readonly ImmutableArray s_hostAnalyzerDlls = ImmutableArray.Create( - "Microsoft.CodeAnalysis.CSharp.dll", - "Microsoft.CodeAnalysis.VisualBasic.dll", - "Microsoft.CodeAnalysis.Features.dll", - "Microsoft.CodeAnalysis.Workspaces.dll", - "Microsoft.CodeAnalysis.CSharp.Workspaces.dll", - "Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll", - "Microsoft.CodeAnalysis.CSharp.Features.dll", - "Microsoft.CodeAnalysis.VisualBasic.Features.dll"); - - public LanguageServerWorkspace(Solution solution, HostServices host, VSCodeAnalyzerLoader vsCodeAnalyzerLoader, ILogger logger, string? workspaceKind) : base(host, workspaceKind) - { - SetCurrentSolution(solution); - InitializeDiagnostics(vsCodeAnalyzerLoader, logger); - } - - internal static async Task CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, HostServices hostServices, ILoggerFactory loggerFactory) - { - var logger = loggerFactory.CreateLogger(nameof(LanguageServerWorkspace)); - try - { - // This is weird. Really we don't need a workspace other than it is a useful tool to keep track of LSP changes. - // But no changes should ever be applied from the LSP host (instead the client should be applying them). - // - // So we use the MSBuildWorkspace type to create the solution. But we can't use the MSBuild workspace itself - // because it doesn't support adding analyzers to the solution (and generallly we shouldn't be calling TryApplyChanges). - // Instead we just take the solution and it put in this workspace type where we can call SetCurrentSolution. - // - // This is all going to get refactored anyway when we do more project system stuff. - using var msbuildWorkspace = MSBuildWorkspace.Create(hostServices); - var solution = await msbuildWorkspace.OpenSolutionAsync(solutionPath).ConfigureAwait(false); - - var vscodeAnalyzerLoader = exportProvider.GetExportedValue(); - var hostWorkspace = new LanguageServerWorkspace(solution, hostServices, vscodeAnalyzerLoader, logger, WorkspaceKind.Host); - // SetCurrentSolution does raise workspace events. For now manually register until we figure out how workspaces will work. - exportProvider.GetExportedValue().Register(hostWorkspace); - - return hostWorkspace; - } - catch (Exception ex) - { - logger.LogError(ex, $"Failed to load workspace for {solutionPath}"); - throw; - } - } - - internal void InitializeDiagnostics(VSCodeAnalyzerLoader vscodeAnalyzerLoader, ILogger logger) + public LanguageServerWorkspace(HostServices host) : base(host, WorkspaceKind.Host) { - var baseDirectory = AppContext.BaseDirectory; - var references = new List(); - var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader(); - foreach (var assemblyName in s_hostAnalyzerDlls) - { - var path = Path.Combine(baseDirectory, assemblyName); - if (!File.Exists(path)) - continue; - - references.Add(new AnalyzerFileReference(path, analyzerLoader)); - } - - var newSolution = this.CurrentSolution.WithAnalyzerReferences(references); - SetCurrentSolution(newSolution); - logger.LogDebug($"Loaded host analyzers:{Environment.NewLine}{string.Join(Environment.NewLine, references.Select(r => r.FullPath))}"); - - vscodeAnalyzerLoader.InitializeDiagnosticsServices(this); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs new file mode 100644 index 0000000000000..0b0e5d45b097c --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs @@ -0,0 +1,168 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.MSBuild; +using Microsoft.CodeAnalysis.ProjectSystem; +using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +/// +/// Represents a single project loaded for a single target. +/// +internal sealed class LoadedProject : IDisposable +{ + private readonly ProjectSystemProject _projectSystemProject; + private readonly ProjectSystemProjectOptionsProcessor _optionsProcessor; + private readonly IFileChangeContext _fileChangeContext; + + /// + /// The most recent version of the project design time build information; held onto so the next reload we can diff against this. + /// + private ProjectFileInfo? _mostRecentFileInfo; + private ImmutableArray _mostRecentMetadataReferences = ImmutableArray.Empty; + + public LoadedProject(ProjectSystemProject projectSystemProject, SolutionServices solutionServices, IFileChangeWatcher fileWatcher) + { + Contract.ThrowIfNull(projectSystemProject.FilePath); + + _projectSystemProject = projectSystemProject; + _optionsProcessor = new ProjectSystemProjectOptionsProcessor(projectSystemProject, solutionServices); + + // We'll watch the directory for all source file changes + // TODO: we only should listen for add/removals here, but we can't specify such a filter now + var watchedDirectory = new WatchedDirectory(Path.GetDirectoryName(projectSystemProject.FilePath)!, ".cs"); + + _fileChangeContext = fileWatcher.CreateContext(watchedDirectory); + _fileChangeContext.FileChanged += FileChangedContext_FileChanged; + + // Start watching for file changes for the project file as well + _fileChangeContext.EnqueueWatchingFile(projectSystemProject.FilePath); + } + + private void FileChangedContext_FileChanged(object? sender, string filePath) + { + NeedsReload?.Invoke(this, EventArgs.Empty); + } + + public event EventHandler? NeedsReload; + + public string? GetTargetFramework() + { + Contract.ThrowIfNull(_mostRecentFileInfo, "We haven't been given a loaded project yet, so we can't provide the existing TFM."); + return _mostRecentFileInfo.TargetFramework; + } + + public void Dispose() + { + _optionsProcessor.Dispose(); + _projectSystemProject.RemoveFromWorkspace(); + } + + public async ValueTask UpdateWithNewProjectInfoAsync(ProjectFileInfo newProjectInfo) + { + if (_mostRecentFileInfo != null) + { + // We should never be changing the fundamental identity of this project; if this happens we really should have done a full unload/reload. + Contract.ThrowIfFalse(newProjectInfo.FilePath == _mostRecentFileInfo.FilePath); + Contract.ThrowIfFalse(newProjectInfo.TargetFramework == _mostRecentFileInfo.TargetFramework); + } + + await using var batch = _projectSystemProject.CreateBatchScope().ConfigureAwait(false); + + var projectDisplayName = Path.GetFileNameWithoutExtension(newProjectInfo.FilePath); + + if (newProjectInfo.TargetFramework != null) + { + projectDisplayName += " (" + newProjectInfo.TargetFramework + ")"; + } + + _projectSystemProject.OutputFilePath = newProjectInfo.OutputFilePath; + _projectSystemProject.OutputRefFilePath = newProjectInfo.OutputRefFilePath; + + _optionsProcessor.SetCommandLine(newProjectInfo.CommandLineArgs); + + UpdateProjectSystemProjectCollection( + newProjectInfo.Documents, + _mostRecentFileInfo?.Documents, + DocumentFileInfoComparer.Instance, + document => _projectSystemProject.AddSourceFile(document.FilePath), + document => _projectSystemProject.RemoveSourceFile(document.FilePath)); + + var metadataReferences = _optionsProcessor.GetParsedCommandLineArguments().MetadataReferences; + + UpdateProjectSystemProjectCollection( + metadataReferences, + _mostRecentMetadataReferences, + EqualityComparer.Default, // CommandLineReference already implements equality + reference => _projectSystemProject.AddMetadataReference(reference.Reference, reference.Properties), + reference => _projectSystemProject.RemoveMetadataReference(reference.Reference, reference.Properties)); + + // Now that we've updated it hold onto the old list of references so we can remove them if there's a later update + _mostRecentMetadataReferences = metadataReferences; + + UpdateProjectSystemProjectCollection( + newProjectInfo.AdditionalDocuments.Distinct(DocumentFileInfoComparer.Instance), // TODO: figure out why we have duplicates + _mostRecentFileInfo?.AdditionalDocuments.Distinct(DocumentFileInfoComparer.Instance), + DocumentFileInfoComparer.Instance, + document => _projectSystemProject.AddAdditionalFile(document.FilePath), + document => _projectSystemProject.RemoveAdditionalFile(document.FilePath)); + + UpdateProjectSystemProjectCollection( + newProjectInfo.AnalyzerConfigDocuments, + _mostRecentFileInfo?.AnalyzerConfigDocuments, + DocumentFileInfoComparer.Instance, + document => _projectSystemProject.AddAnalyzerConfigFile(document.FilePath), + document => _projectSystemProject.RemoveAnalyzerConfigFile(document.FilePath)); + + _mostRecentFileInfo = newProjectInfo; + + return; + + static void UpdateProjectSystemProjectCollection(IEnumerable loadedCollection, IEnumerable? oldLoadedCollection, IEqualityComparer comparer, Action addItem, Action removeItem) + { + var oldItems = new HashSet(comparer); + + if (oldLoadedCollection != null) + { + foreach (var item in oldLoadedCollection) + oldItems.Add(item); + } + + foreach (var newItem in loadedCollection) + { + // If oldItems already has this, we don't need to add it again. We'll remove it, and what is left in oldItems is stuff to remove + if (!oldItems.Remove(newItem)) + addItem(newItem); + } + + foreach (var oldItem in oldItems) + { + removeItem(oldItem); + } + } + } + + private sealed class DocumentFileInfoComparer : IEqualityComparer + { + public static IEqualityComparer Instance = new DocumentFileInfoComparer(); + + private DocumentFileInfoComparer() + { + } + + public bool Equals(DocumentFileInfo? x, DocumentFileInfo? y) + { + return StringComparer.Ordinal.Equals(x?.FilePath, y?.FilePath); + } + + public int GetHashCode(DocumentFileInfo obj) + { + return StringComparer.Ordinal.GetHashCode(obj.FilePath); + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs new file mode 100644 index 0000000000000..e4261f21e3dab --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +[ExportWorkspaceServiceFactory(typeof(IMetadataService), ServiceLayer.Host)] +internal sealed class MetadataServiceFactory : IWorkspaceServiceFactory +{ + public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) + { + return new MetadataService(workspaceServices.GetRequiredService()); + } + + internal sealed class MetadataService : IMetadataService + { + private readonly IDocumentationProviderService _documentationProviderService; + + public MetadataService(IDocumentationProviderService documentationProviderService) + { + _documentationProviderService = documentationProviderService; + } + + public PortableExecutableReference GetReference(string resolvedPath, MetadataReferenceProperties properties) + { + // HACK: right now the FileWatchedPortableExecutableReferenceFactory in Roslyn presumes that each time it calls IMetadataService + // it gets a unique instance back; the default MetadataService at the workspace layer has a cache to encourage sharing, but that + // breaks the assumption. + try + { + return MetadataReference.CreateFromFile(resolvedPath, properties, _documentationProviderService.GetDocumentationProvider(resolvedPath)); + } + catch (IOException ex) + { + return new ThrowingExecutableReference(resolvedPath, properties, ex); + } + } + + private class ThrowingExecutableReference : PortableExecutableReference + { + private readonly IOException _ex; + + public ThrowingExecutableReference(string resolvedPath, MetadataReferenceProperties properties, IOException ex) : base(properties, resolvedPath) + { + _ex = ex; + } + + protected override DocumentationProvider CreateDocumentationProvider() + { + throw new NotImplementedException(); + } + + protected override Metadata GetMetadataImpl() + { + throw _ex; + } + + protected override PortableExecutableReference WithPropertiesImpl(MetadataReferenceProperties properties) + { + return new ThrowingExecutableReference(FilePath!, properties, _ex); + } + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index bdad50eae96b3..fcaed0a2041c9 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -17,6 +17,7 @@ + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index dceef8fbf7674..96e4ab43756bb 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -2,15 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Immutable; using System.Diagnostics; using Microsoft.Build.Locator; -using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Elfie.Extensions; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.Composition; Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; @@ -45,15 +45,22 @@ // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); -var hostServices = exportProvider.GetExportedValue().HostServices; +// Create the project system first, since right now the language server will assume there's at least one Workspace +var projectSystem = exportProvider.GetExportedValue(); -using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory).ConfigureAwait(false)) -{ - var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); +var analyzerPaths = new DirectoryInfo(AppContext.BaseDirectory).GetFiles("*.dll") + .Where(f => f.Name.StartsWith("Microsoft.CodeAnalysis.", StringComparison.Ordinal) && !f.Name.Contains("LanguageServer", StringComparison.Ordinal)) + .Select(f => f.FullName) + .ToImmutableArray(); - server.Start(); - await server.WaitForExitAsync().ConfigureAwait(false); -} +await projectSystem.InitializeSolutionLevelAnalyzersAsync(analyzerPaths).ConfigureAwait(false); + +var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); +server.Start(); + +projectSystem.OpenSolution(solutionPath); + +await server.WaitForExitAsync().ConfigureAwait(false); // Dispose of our container, so parts can cleanly shut themselves down exportProvider.Dispose(); From 7667854de1c880cbff09dc5d501d9fdb9a9b0fe0 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Mon, 6 Feb 2023 19:53:57 -0800 Subject: [PATCH 033/261] Ensure we dedup project paths being added to the background batch If we don't do this, we'll try loading the MSBuild project twice in the same project collection which will throw exceptions. --- .../HostWorkspace/LanguageServerProjectSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index b55fa1b2e493b..844a348b57d66 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -52,6 +52,7 @@ public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VS _projectsToLoadAndReload = new AsyncBatchingWorkQueue( TimeSpan.FromMilliseconds(100), LoadOrReloadProjectsAsync, + StringComparer.Ordinal, listenerProvider.GetListener(FeatureAttribute.Workspace), CancellationToken.None); // TODO: do we need to introduce a shutdown cancellation token for this? From 16530db896b435290b9684de3ea977ca9f481855 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 14 Feb 2023 01:34:11 +0000 Subject: [PATCH 034/261] Merged PR 451859: Remove rule requiring ConfigureAwait() Remove rule requiring ConfigureAwait() We don't have a UI thread so this is basically just noise. --- src/Features/LanguageServer/.editorconfig | 7 +------ .../AbstractLanguageServerHostTests.cs | 8 ++++---- .../ExportProviderBuilder.cs | 4 ++-- .../HostWorkspace/LanguageServerProjectSystem.cs | 14 +++++++------- .../HostWorkspace/LoadedProject.cs | 2 +- .../LanguageServer/LanguageServerHost.cs | 4 ++-- .../Program.cs | 7 +++---- 7 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/Features/LanguageServer/.editorconfig b/src/Features/LanguageServer/.editorconfig index 821d99ae91d6e..7db6f64aca2e0 100644 --- a/src/Features/LanguageServer/.editorconfig +++ b/src/Features/LanguageServer/.editorconfig @@ -184,7 +184,7 @@ dotnet_style_prefer_conditional_expression_over_assignment = true:warning dotnet_diagnostic.CA1802.severity = warning # CA2007: Do not directly await a Task -dotnet_diagnostic.CA2007.severity = warning +dotnet_diagnostic.CA2007.severity = none # CA2016: Forward the CancellationToken parameter to methods that take one dotnet_diagnostic.CA2016.severity = warning @@ -322,8 +322,3 @@ dotnet_diagnostic.IDE2003.severity = warning # csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental dotnet_diagnostic.IDE2004.severity = warning - -[{Microsoft.CodeAnalysis.LanguageServer.UnitTests/*.cs}] -# For tests, the ConfigureAwait(true) is good enough. They are already running on a thread pool -# thread where ConfigureAwait(false) does nothing. -dotnet_diagnostic.CA2007.severity = none diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs index 5f2320b691ff4..ef3b0d3dbd4df 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -65,18 +65,18 @@ private TestLspServer(ExportProvider exportProvider, ILogger logger) public async Task ExecuteRequestAsync(string methodName, TRequestType request, CancellationToken cancellationToken) where TRequestType : class { - var result = await _clientRpc.InvokeWithParameterObjectAsync(methodName, request, cancellationToken: cancellationToken).ConfigureAwait(false); + var result = await _clientRpc.InvokeWithParameterObjectAsync(methodName, request, cancellationToken: cancellationToken); return result; } public async ValueTask DisposeAsync() { - await _clientRpc.InvokeAsync(Methods.ShutdownName).ConfigureAwait(false); - await _clientRpc.NotifyAsync(Methods.ExitName).ConfigureAwait(false); + await _clientRpc.InvokeAsync(Methods.ShutdownName); + await _clientRpc.NotifyAsync(Methods.ExitName); // The language server host task should complete once shutdown and exit are called. #pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks - await _languageServerHostCompletionTask.ConfigureAwait(false); + await _languageServerHostCompletionTask; #pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks _clientRpc.Dispose(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 316dfed0c86b3..2f8eec232e5f1 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -25,8 +25,8 @@ public static async Task CreateExportProviderAsync() // TODO - we should likely cache the catalog so we don't have to rebuild it every time. var catalog = ComposableCatalog.Create(Resolver.DefaultInstance) - .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()).ConfigureAwait(false)) - .AddParts(await discovery.CreatePartsAsync(assembliesToDiscover).ConfigureAwait(false)) + .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly())) + .AddParts(await discovery.CreatePartsAsync(assembliesToDiscover)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import // Assemble the parts into a valid graph. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index 844a348b57d66..22309bbe8c580 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -84,7 +84,7 @@ public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray a } } - await _projectSystemProjectFactory.ApplyChangeToWorkspaceAsync(w => w.SetCurrentSolution(s => s.WithAnalyzerReferences(references), WorkspaceChangeKind.SolutionChanged)).ConfigureAwait(false); + await _projectSystemProjectFactory.ApplyChangeToWorkspaceAsync(w => w.SetCurrentSolution(s => s.WithAnalyzerReferences(references), WorkspaceChangeKind.SolutionChanged)); } public void OpenSolution(string solutionFilePath) @@ -122,7 +122,7 @@ private async ValueTask LoadOrReloadProjectsAsync(ImmutableSegmentedList tasks.Add(Task.Run(() => LoadOrReloadProjectAsync(projectPathToLoadOrReload, projectBuildManager, disposalToken), disposalToken)); } - await Task.WhenAll(tasks).ConfigureAwait(false); + await Task.WhenAll(tasks); } finally { @@ -138,8 +138,8 @@ private async Task LoadOrReloadProjectAsync(string projectPath, ProjectBuildMana { if (_projectFileLoaderRegistry.TryGetLoaderFromProjectPath(projectPath, out var loader)) { - var loadedFile = await loader.LoadProjectFileAsync(projectPath, projectBuildManager, disposalToken).ConfigureAwait(false); - var loadedProjectInfos = await loadedFile.GetProjectFileInfosAsync(disposalToken).ConfigureAwait(false); + var loadedFile = await loader.LoadProjectFileAsync(projectPath, projectBuildManager, disposalToken); + var loadedProjectInfos = await loadedFile.GetProjectFileInfosAsync(disposalToken); var existingProjects = _loadedProjects.GetOrAdd(projectPath, static _ => new List()); @@ -150,7 +150,7 @@ private async Task LoadOrReloadProjectAsync(string projectPath, ProjectBuildMana if (existingProject != null) { - await existingProject.UpdateWithNewProjectInfoAsync(loadedProjectInfo).ConfigureAwait(false); + await existingProject.UpdateWithNewProjectInfoAsync(loadedProjectInfo); } else { @@ -161,13 +161,13 @@ private async Task LoadOrReloadProjectAsync(string projectPath, ProjectBuildMana projectSystemName, loadedProjectInfo.Language, projectCreationInfo, - _projectHostInfo).ConfigureAwait(false); + _projectHostInfo); var loadedProject = new LoadedProject(projectSystemProject, Workspace.Services.SolutionServices, _fileChangeWatcher); loadedProject.NeedsReload += (_, _) => _projectsToLoadAndReload.AddWork(projectPath); existingProjects.Add(loadedProject); - await loadedProject.UpdateWithNewProjectInfoAsync(loadedProjectInfo).ConfigureAwait(false); + await loadedProject.UpdateWithNewProjectInfoAsync(loadedProjectInfo); } } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs index 0b0e5d45b097c..8d0db9004347c 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs @@ -72,7 +72,7 @@ public async ValueTask UpdateWithNewProjectInfoAsync(ProjectFileInfo newProjectI Contract.ThrowIfFalse(newProjectInfo.TargetFramework == _mostRecentFileInfo.TargetFramework); } - await using var batch = _projectSystemProject.CreateBatchScope().ConfigureAwait(false); + await using var batch = _projectSystemProject.CreateBatchScope(); var projectDisplayName = Path.GetFileNameWithoutExtension(newProjectInfo.FilePath); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index 27a130b9f043a..1fd6288384dde 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -57,8 +57,8 @@ public void Start() public async Task WaitForExitAsync() { - await _jsonRpc.Completion.ConfigureAwait(false); - await _roslynLanguageServer.WaitForExitAsync().ConfigureAwait(false); + await _jsonRpc.Completion; + await _roslynLanguageServer.WaitForExitAsync(); } public Task NotifyAsync(string targetName, object? argument) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 96e4ab43756bb..de089f7a42ae4 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -5,7 +5,6 @@ using System.Collections.Immutable; using System.Diagnostics; using Microsoft.Build.Locator; -using Microsoft.CodeAnalysis.Elfie.Extensions; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; @@ -40,7 +39,7 @@ var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); MSBuildLocator.RegisterInstance(msbuildInstances.First()); -var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync().ConfigureAwait(false); +var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); @@ -53,14 +52,14 @@ .Select(f => f.FullName) .ToImmutableArray(); -await projectSystem.InitializeSolutionLevelAnalyzersAsync(analyzerPaths).ConfigureAwait(false); +await projectSystem.InitializeSolutionLevelAnalyzersAsync(analyzerPaths); var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); server.Start(); projectSystem.OpenSolution(solutionPath); -await server.WaitForExitAsync().ConfigureAwait(false); +await server.WaitForExitAsync(); // Dispose of our container, so parts can cleanly shut themselves down exportProvider.Dispose(); From 66ed5c805ac0b9526320ee8a16702506ac3aa6bb Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 16 Feb 2023 21:00:28 +0000 Subject: [PATCH 035/261] Merged PR 451301: Connect to Green via brokered services Related - https://devdiv.visualstudio.com/DevDiv/_git/vs-green-server/pullrequest/451302 --- src/Features/LanguageServer/.editorconfig | 3 + .../LanguageServer/Directory.Packages.props | 5 +- .../BrokeredServiceBridgeProvider.cs | 76 +++++++++++++++++++ .../BrokeredServiceContainer.cs | 74 ++++++++++++++++++ .../BrokeredServiceTraceLogger.cs | 35 +++++++++ .../BrokeredServices/MefServiceBroker.cs | 26 +++++++ .../ServiceBrokerMefExport.cs | 29 +++++++ .../BrokeredServiceBridgeManifestService.cs | 45 +++++++++++ .../IBrokeredServiceBridgeManifest.cs | 24 ++++++ .../BrokeredServices/Services/Descriptors.cs | 40 ++++++++++ .../Services/HelloWorld/HelloWorldService.cs | 32 ++++++++ .../Services/HelloWorld/IHelloWorld.cs | 21 +++++ .../HelloWorld/RemoteHelloWorldProvider.cs | 67 ++++++++++++++++ .../ExportProviderBuilder.cs | 1 + ...crosoft.CodeAnalysis.LanguageServer.csproj | 9 ++- .../Program.cs | 52 +++++++++---- 16 files changed, 520 insertions(+), 19 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/Descriptors.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/IHelloWorld.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs diff --git a/src/Features/LanguageServer/.editorconfig b/src/Features/LanguageServer/.editorconfig index 7db6f64aca2e0..c061b32160bdf 100644 --- a/src/Features/LanguageServer/.editorconfig +++ b/src/Features/LanguageServer/.editorconfig @@ -322,3 +322,6 @@ dotnet_diagnostic.IDE2003.severity = warning # csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental dotnet_diagnostic.IDE2004.severity = warning + +# VSTHRD003: Avoid awaiting foreign Tasks +dotnet_diagnostic.VSTHRD003.severity = none diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 82755fcab37b8..558b5de9ea145 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -13,10 +13,13 @@ 6.0.0 6.0.2 $(MicrosoftExtensionsLoggingVersion) + + 4.2.49-beta + $(ServiceBrokerVersion) 17.2.41 17.5.20-preview 2.9.112 - 2.14.20 + 2.15.3-alpha diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs new file mode 100644 index 0000000000000..2a8393b616b77 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Composition; +using System.Diagnostics; +using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; +using Microsoft.Extensions.Logging; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; +using Microsoft.VisualStudio.Utilities.ServiceBroker; +using Nerdbank.Streams; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; + +[Export, Shared] +internal class BrokeredServiceBridgeProvider +{ + private const string ServiceBrokerChannelName = "serviceBroker"; + + private readonly ILogger _logger; + private readonly TraceSource _brokeredServiceTraceSource; + + [ImportingConstructor] + public BrokeredServiceBridgeProvider(ILoggerFactory loggerFactory, BrokeredServiceTraceListener brokeredServiceTraceListener) + { + _logger = loggerFactory.CreateLogger(); + _brokeredServiceTraceSource = brokeredServiceTraceListener.Source; + } + + /// + /// Creates the brokered service bridge to the remote process. + /// We expose the services from our container to the remote and consume services + /// from the remote by proffering them into our container. + /// + /// the pipe name we use for the connection. + /// our local container. + /// a cancellation token. + /// a task that represents the lifetime of the bridge. It will complete when the bridge closes. + public async Task SetupBrokeredServicesBridgeAsync(string brokeredServicePipeName, BrokeredServiceContainer container, CancellationToken cancellationToken) + { + _logger.LogInformation("Setting up brokered service bridge"); + using var bridgeStream = await ServerFactory.ConnectAsync(brokeredServicePipeName, cancellationToken); + using var bridgeMxStream = await MultiplexingStream.CreateAsync(bridgeStream, cancellationToken); + + // Wait until the connection ends (so we don't dispose of the stream before it ends). + await Task.WhenAll(ProfferServicesToRemoteAsync(), ConsumeServicesFromRemoteAsync()); + + async Task ProfferServicesToRemoteAsync() + { + using var profferedServiceBrokerChannel = await bridgeMxStream.OfferChannelAsync(ServiceBrokerChannelName, cancellationToken); + var serviceBroker = container.GetLimitedAccessServiceBroker(ServiceAudience.Local, ImmutableDictionary.Empty, ClientCredentialsPolicy.RequestOverridesDefault); + using IpcRelayServiceBroker relayServiceBroker = new(serviceBroker); + + FrameworkServices.RemoteServiceBroker + .WithTraceSource(_brokeredServiceTraceSource) + .ConstructRpc(relayServiceBroker, profferedServiceBrokerChannel); + + await relayServiceBroker.Completion; + } + + async Task ConsumeServicesFromRemoteAsync() + { + using var consumingServiceBrokerChannel = await bridgeMxStream.AcceptChannelAsync(ServiceBrokerChannelName, cancellationToken); + var remoteClient = FrameworkServices.RemoteServiceBroker + .WithTraceSource(_brokeredServiceTraceSource) + .ConstructRpc(consumingServiceBrokerChannel); + + using (container.ProfferRemoteBroker(remoteClient, bridgeMxStream, ServiceSource.OtherProcessOnSameMachine, Descriptors.RemoteServicesToRegister.Keys.ToImmutableHashSet())) + { + await consumingServiceBrokerChannel.Completion; + } + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs new file mode 100644 index 0000000000000..957255ba110d2 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Diagnostics; +using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; +using Microsoft.ServiceHub.Framework; +using Microsoft.ServiceHub.Framework.Services; +using Microsoft.VisualStudio.Composition; +using Microsoft.VisualStudio.Threading; +using Microsoft.VisualStudio.Utilities.ServiceBroker; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; +internal class BrokeredServiceContainer : GlobalBrokeredServiceContainer +{ + public BrokeredServiceContainer(TraceSource traceSource) + : base(ImmutableDictionary.Empty, isClientOfExclusiveServer: false, joinableTaskFactory: null, traceSource) + { + } + + public override IReadOnlyDictionary LocalUserCredentials + => ImmutableDictionary.Empty; + + /// + internal new void RegisterServices(IReadOnlyDictionary services) + => base.RegisterServices(services); + + internal ImmutableDictionary GetRegisteredServices() + => RegisteredServices; + + internal static async Task CreateAsync(ExportProvider exportProvider, CancellationToken cancellationToken) + { + var traceListener = exportProvider.GetExportedValue(); + var container = new BrokeredServiceContainer(traceListener.Source); + exportProvider.GetExportedValue().Container = container; + + container.ProfferIntrinsicService( + FrameworkServices.Authorization, + new ServiceRegistration(VisualStudio.Shell.ServiceBroker.ServiceAudience.Local, null, allowGuestClients: true), + (moniker, options, serviceBroker, cancellationToken) => new(new NoOpAuthorizationService())); + + var mefServiceBroker = exportProvider.GetExportedValue(); + + // Register local mef services. + await mefServiceBroker.RegisterAndProfferServicesAsync(cancellationToken); + + // Register the desired remote services + container.RegisterServices(Descriptors.RemoteServicesToRegister); + + return container; + } + + private class NoOpAuthorizationService : IAuthorizationService + { + public event EventHandler? CredentialsChanged; + + public event EventHandler? AuthorizationChanged; + + public ValueTask CheckAuthorizationAsync(ProtectedOperation operation, CancellationToken cancellationToken = default) + { + return new(true); + } + + public ValueTask> GetCredentialsAsync(CancellationToken cancellationToken = default) + { + return new(ImmutableDictionary.Empty); + } + + protected virtual void OnCredentialsChanged(EventArgs args) => this.CredentialsChanged?.Invoke(this, args); + + protected virtual void OnAuthorizationChanged(EventArgs args) => this.AuthorizationChanged?.Invoke(this, args); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs new file mode 100644 index 0000000000000..4d38a6eb8bb82 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using System.Diagnostics; +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; + +[Export, Shared] +internal class BrokeredServiceTraceListener : TraceListener +{ + private readonly ILogger _logger; + + public TraceSource Source { get; } + + [ImportingConstructor] + public BrokeredServiceTraceListener(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(nameof(BrokeredServiceTraceListener)); + Source = new TraceSource("ServiceBroker", SourceLevels.ActivityTracing); + Source.Listeners.Add(this); + } + + public override void Write(string? message) + { + _logger.LogDebug(message); + } + + public override void WriteLine(string? message) + { + _logger.LogDebug(message); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs new file mode 100644 index 0000000000000..43a1361fbf9b4 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using Microsoft.VisualStudio.Shell.ServiceBroker; +using Microsoft.VisualStudio.Utilities.ServiceBroker; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; + +[Export, Shared] +internal class MefServiceBroker : ServiceBrokerOfExportedServices +{ + private Task? containerTask; + + [Import("PrivateBrokeredServiceContainer")] + internal BrokeredServiceContainer BrokeredServiceContainer { get; private set; } = null!; + + protected override Task GetBrokeredServiceContainerAsync(CancellationToken cancellationToken) + { + Contract.ThrowIfNull(BrokeredServiceContainer, $"{nameof(this.BrokeredServiceContainer)} must be set first."); + this.containerTask ??= Task.FromResult((GlobalBrokeredServiceContainer)this.BrokeredServiceContainer); + return this.containerTask; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs new file mode 100644 index 0000000000000..e350400c67047 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Composition; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; + +/// +/// Exports an for convenient and potentially cross-IDE importing by other features. +/// +/// +/// Each import site gets its own instance to match the behavior of calling +/// which returns a private instance for everyone. +/// This is observable to callers in a few ways, including that they only get the events +/// based on their own service queries. +/// MEF will dispose of each instance as its lifetime comes to an end. +/// +[Export] +internal class ServiceBrokerMefExport +{ + [Export(typeof(SVsFullAccessServiceBroker))] + public IServiceBroker ServiceBroker => this.Container?.GetFullAccessServiceBroker() ?? throw new InvalidOperationException($"Set {nameof(this.Container)} first."); + + [Export("PrivateBrokeredServiceContainer")] + internal BrokeredServiceContainer? Container { get; set; } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs new file mode 100644 index 0000000000000..551b2dc7b0724 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.ComponentModel.Composition; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.BrokeredServiceBridgeManifest; + +[ExportBrokeredService(MonikerName, MonikerVersion, Audience = ServiceAudience.Local)] +internal class BrokeredServiceBridgeManifest : IBrokeredServiceBridgeManifest, IExportedBrokeredService +{ + internal const string MonikerName = "Microsoft.VisualStudio.Server.IBrokeredServiceBridgeManifest"; + internal const string MonikerVersion = "0.1"; + private static readonly ServiceMoniker s_serviceMoniker = new ServiceMoniker(MonikerName, new Version(MonikerVersion)); + private static readonly ServiceRpcDescriptor s_serviceDescriptor = new ServiceJsonRpcDescriptor( + s_serviceMoniker, + ServiceJsonRpcDescriptor.Formatters.UTF8, + ServiceJsonRpcDescriptor.MessageDelimiters.HttpLikeHeaders); + + private readonly BrokeredServiceContainer _container; + + [ImportingConstructor] + public BrokeredServiceBridgeManifest([Import("PrivateBrokeredServiceContainer")] BrokeredServiceContainer container) + { + _container = container; + } + + public ServiceRpcDescriptor Descriptor => s_serviceDescriptor; + + public ValueTask> GetAvailableServicesAsync(CancellationToken cancellationToken) + { + return ValueTask.FromResult((IReadOnlyCollection)_container.GetRegisteredServices() + .Select(s => s.Key) + .Where(s => s.Name.StartsWith("Microsoft.CodeAnalysis.LanguageServer", StringComparison.Ordinal)) + .ToImmutableArray()); + } + + public Task InitializeAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs new file mode 100644 index 0000000000000..750502a70b6f2 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.ServiceHub.Framework; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.BrokeredServiceBridgeManifest; + +/// +/// Defines a service to be used by the remote party to determine which services from this container +/// it should add to its container. This is useful in the case where the remote party connects to other processes +/// that proffer the same services as we do (e.g. intrinsic services). +/// Both are proffered as and therefore conflict. +/// +internal interface IBrokeredServiceBridgeManifest +{ + /// + /// Returns services that the container wishes to expose across the bridge. + /// + /// + /// + ValueTask> GetAvailableServicesAsync(CancellationToken cancellationToken); +} + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/Descriptors.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/Descriptors.cs new file mode 100644 index 0000000000000..bbf8bc5fb578b --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/Descriptors.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; +using Microsoft.VisualStudio.Utilities.ServiceBroker; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; + +internal class Descriptors +{ + // Descriptors for remote services. + // If adding services here, make sure to update RemoteServicesToRegister. + + public static readonly ServiceRpcDescriptor RemoteHelloWorldService = CreateDescriptor(new("helloServiceHubDotNetHost", new Version("0.1"))); + + // Descriptors for local services. + + public static readonly ServiceRpcDescriptor LocalHelloWorldService = CreateDescriptor(new(HelloWorldService.MonikerName, new Version(HelloWorldService.MonikerVersion))); + + /// + /// The set of remote services that we register to our container. + /// + /// + /// Note that while today we only support static registration of services in the remote process it would be possible to implement dynamic registration + /// if we read the remote brokered service manifest. + /// + public static ImmutableDictionary RemoteServicesToRegister = new Dictionary + { + { Descriptors.RemoteHelloWorldService.Moniker, new ServiceRegistration(ServiceAudience.Local, null, allowGuestClients: false) }, + }.ToImmutableDictionary(); + + public static ServiceJsonRpcDescriptor CreateDescriptor(ServiceMoniker serviceMoniker) => new( + serviceMoniker, + ServiceJsonRpcDescriptor.Formatters.UTF8, + ServiceJsonRpcDescriptor.MessageDelimiters.HttpLikeHeaders); +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs new file mode 100644 index 0000000000000..4a38f54762f61 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; + +[ExportBrokeredService(MonikerName, MonikerVersion, Audience = ServiceAudience.AllClientsIncludingGuests | ServiceAudience.Local)] +internal class HelloWorldService : IHelloWorld, IExportedBrokeredService +{ + internal const string MonikerName = "Microsoft.CodeAnalysis.LanguageServer.IHelloWorld"; + internal const string MonikerVersion = "0.1"; + + public ServiceRpcDescriptor Descriptor => Descriptors.LocalHelloWorldService; + + public Task InitializeAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + public Task SayHelloAsync(string name, CancellationToken cancellationToken) + { + return Task.FromResult($"Greetings {name}, welcome to the blue party :)"); + } + + public Task CallMeAsync(ServiceMoniker serviceMoniker, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/IHelloWorld.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/IHelloWorld.cs new file mode 100644 index 0000000000000..1dc738ce759f5 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/IHelloWorld.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.ServiceHub.Framework; +using StreamJsonRpc; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; + +/// +/// A simple interface used for sanity checking that the brokered service bridge works. +/// There is an implementation of the same service on the green side that we can talk to. +/// +internal interface IHelloWorld +{ + [JsonRpcMethod("sayHello")] + Task SayHelloAsync(string name, CancellationToken cancellationToken); + + [JsonRpcMethod("callMe")] + Task CallMeAsync(ServiceMoniker serviceMoniker, CancellationToken cancellationToken); +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs new file mode 100644 index 0000000000000..35591f7f1eda4 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel.Composition; +using Microsoft.Extensions.Logging; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; + +[Export] +internal class RemoteHelloWorldProvider +{ + private readonly IServiceBroker _serviceBroker; + private readonly TaskCompletionSource _serviceAvailable = new(); + private readonly ILogger _logger; + + [ImportingConstructor] + public RemoteHelloWorldProvider([Import(typeof(SVsFullAccessServiceBroker))] IServiceBroker serviceBroker, ILoggerFactory loggerFactory) + { + _serviceBroker = serviceBroker; + _logger = loggerFactory.CreateLogger(); + + _serviceBroker.AvailabilityChanged += ServiceBroker_AvailabilityChanged; + } + + public async Task SayHelloToRemoteServerAsync(CancellationToken cancellationToken) + { + var response = await TryGetHelloWorldAsync(cancellationToken); + if (!response) + { + await _serviceAvailable.Task; + Contract.ThrowIfFalse(await TryGetHelloWorldAsync(cancellationToken), "Was not able to get hello world response from remote"); + } + } + + private void ServiceBroker_AvailabilityChanged(object? sender, BrokeredServicesChangedEventArgs e) + { + if (e.ImpactedServices.Contains(Descriptors.RemoteHelloWorldService.Moniker)) + _serviceAvailable.SetResult(); + } + + private async Task TryGetHelloWorldAsync(CancellationToken cancellationToken) + { + var helloWorldService = await _serviceBroker.GetProxyAsync(Descriptors.RemoteHelloWorldService, cancellationToken); + using (helloWorldService as IDisposable) + { + if (helloWorldService is not null) + { + try + { + var callback = await helloWorldService.CallMeAsync(Descriptors.LocalHelloWorldService.Moniker, cancellationToken); + _logger.LogInformation("Callback from remote: " + callback); + return true; + } + catch (Exception ex) + { + _logger.LogError($"Got exception when invoking callback function:{ex}"); + } + } + } + + return false; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 2f8eec232e5f1..8d195857e4bde 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -18,6 +18,7 @@ public static async Task CreateExportProviderAsync() // Load any Roslyn assemblies from the extension directory var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll"); + assembliesToDiscover = assembliesToDiscover.Concat(Directory.EnumerateFiles(baseDirectory, "Microsoft.ServiceHub*.dll")); var discovery = PartDiscovery.Combine( new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index fcaed0a2041c9..689054871f82d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -9,8 +9,8 @@ False - $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) - $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/neutral + $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) + $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/neutral 7.0.0-preview.7.22362.8 LatestMajor @@ -25,9 +25,10 @@ - + + @@ -37,4 +38,4 @@ - + \ No newline at end of file diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index de089f7a42ae4..dcefd967db055 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -6,6 +6,8 @@ using System.Diagnostics; using Microsoft.Build.Locator; using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; +using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Logging; @@ -39,11 +41,22 @@ var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); MSBuildLocator.RegisterInstance(msbuildInstances.First()); -var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); +using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); +var brokeredServicePipeName = GetBrokeredServicePipeName(args); +var bridgeCompletionTask = Task.CompletedTask; +if (brokeredServicePipeName != null) +{ + var container = await BrokeredServiceContainer.CreateAsync(exportProvider, CancellationToken.None); + + var bridgeProvider = exportProvider.GetExportedValue(); + + bridgeCompletionTask = bridgeProvider.SetupBrokeredServicesBridgeAsync(brokeredServicePipeName, container, CancellationToken.None); +} + // Create the project system first, since right now the language server will assume there's at least one Workspace var projectSystem = exportProvider.GetExportedValue(); @@ -59,28 +72,29 @@ projectSystem.OpenSolution(solutionPath); +if (brokeredServicePipeName != null) +{ + await exportProvider.GetExportedValue().SayHelloToRemoteServerAsync(CancellationToken.None); +} + await server.WaitForExitAsync(); -// Dispose of our container, so parts can cleanly shut themselves down -exportProvider.Dispose(); -loggerFactory.Dispose(); +await bridgeCompletionTask; return; static LogLevel GetLogLevel(string[] args) { - var logLevelIndex = Array.IndexOf(args, "--logLevel") + 1; - if (logLevelIndex > 0) + var logLevel = GetArgumentValue(args, "--logLevel"); + if (logLevel != null) { - // Map VSCode log level to the LogLevel we can use with ILogger APIs. - var level = args[logLevelIndex]; - return level switch + return logLevel switch { "off" => LogLevel.None, "minimal" => LogLevel.Information, "messages" => LogLevel.Debug, "verbose" => LogLevel.Trace, - _ => throw new InvalidOperationException($"Unexpected logLevel argument {level}"), + _ => throw new InvalidOperationException($"Unexpected logLevel argument {logLevel}"), }; } @@ -97,12 +111,22 @@ static void LaunchDebuggerIfEnabled(string[] args) static string GetSolutionPath(string[] args) { - var solutionPathIndex = Array.IndexOf(args, "--solutionPath") + 1; - if (solutionPathIndex == 0 || solutionPathIndex >= args.Length) + return GetArgumentValue(args, "--solutionPath") ?? throw new InvalidOperationException($"Missing valid --solutionPath argument, got {string.Join(",", args)}"); +} + +static string? GetBrokeredServicePipeName(string[] args) +{ + return GetArgumentValue(args, "--brokeredServicePipeName"); +} + +static string? GetArgumentValue(string[] args, string argumentName) +{ + var argumentValueIndex = Array.IndexOf(args, argumentName) + 1; + if (argumentValueIndex > 0 && argumentValueIndex < args.Length) { - throw new InvalidOperationException($"Missing valid --solutionPath argument, got {string.Join(",", args)}"); + return args[argumentValueIndex]; } - return args[solutionPathIndex]; + return null; } From 29746ccf22f82362bb73530d79ae7dc46accaacc Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Fri, 17 Feb 2023 23:32:21 +0000 Subject: [PATCH 036/261] Merged PR 452717: Add a RoslynVersion.txt to publish data This will be used by VS Thunder to determine the correct NuGet version to restore --- ...crosoft.CodeAnalysis.LanguageServer.csproj | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 689054871f82d..92ac47ec669e8 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -1,41 +1,54 @@  - - Exe - net7.0 - enable - enable - ../../artifacts - $(ArtifactsPath)/bin - - - False - $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) - $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/neutral - - 7.0.0-preview.7.22362.8 - LatestMajor - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + Exe + net7.0 + enable + enable + ../../artifacts + $(ArtifactsPath)/bin + + + False + $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) + $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/neutral + + 7.0.0-preview.7.22362.8 + LatestMajor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 16f94c5d320924de13ad473d88d8e1d897066dab Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 21 Feb 2023 22:29:19 +0000 Subject: [PATCH 037/261] Merged PR 453375: Use System.CommandLine for input parsing Use System.CommandLine for input parsing --- .../LanguageServer/Directory.Packages.props | 1 + ...crosoft.CodeAnalysis.LanguageServer.csproj | 1 + .../Program.cs | 199 ++++++++++-------- 3 files changed, 109 insertions(+), 92 deletions(-) diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index 558b5de9ea145..ef0958d4e29b6 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -21,5 +21,6 @@ 17.5.20-preview 2.9.112 2.15.3-alpha + 2.0.0-beta4.22272.1 diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 92ac47ec669e8..3f80a939e1852 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -29,6 +29,7 @@ + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index dcefd967db055..6bfbfbd756205 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -3,6 +3,9 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Parsing; using System.Diagnostics; using Microsoft.Build.Locator; using Microsoft.CodeAnalysis.LanguageServer; @@ -14,119 +17,131 @@ using Microsoft.Extensions.Logging; Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; +var parser = CreateCommandLineParser(); +return await parser.InvokeAsync(args); -var minimumLogLevel = GetLogLevel(args); - -// Before we initialize the LSP server we can't send LSP log messages. -// Create a console logger as a fallback to use before the LSP server starts. -using var loggerFactory = LoggerFactory.Create(builder => -{ - builder.SetMinimumLevel(minimumLogLevel); - builder.AddProvider(new LspLogMessageLoggerProvider(fallbackLoggerFactory: - // Add a console logger as a fallback for when the LSP server has not finished initializing. - LoggerFactory.Create(builder => - { - builder.SetMinimumLevel(minimumLogLevel); - builder.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace); - }) - )); -}); - -LaunchDebuggerIfEnabled(args); - -var solutionPath = GetSolutionPath(args); - -// Register and load the appropriate MSBuild assemblies before we create the MEF composition. -// This is required because we need to include types from MS.CA.Workspaces.MSBuild which has a dependency on MSBuild dlls being loaded. -var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); -MSBuildLocator.RegisterInstance(msbuildInstances.First()); - -using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); - -// Immediately set the logger factory, so that way it'll be available for the rest of the composition -exportProvider.GetExportedValue().SetFactory(loggerFactory); - -var brokeredServicePipeName = GetBrokeredServicePipeName(args); -var bridgeCompletionTask = Task.CompletedTask; -if (brokeredServicePipeName != null) +static async Task RunAsync(bool launchDebugger, string solutionPath, string? brokeredServicePipeName, LogLevel minimumLogLevel, CancellationToken cancellationToken) { - var container = await BrokeredServiceContainer.CreateAsync(exportProvider, CancellationToken.None); - - var bridgeProvider = exportProvider.GetExportedValue(); - - bridgeCompletionTask = bridgeProvider.SetupBrokeredServicesBridgeAsync(brokeredServicePipeName, container, CancellationToken.None); -} - -// Create the project system first, since right now the language server will assume there's at least one Workspace -var projectSystem = exportProvider.GetExportedValue(); + if (launchDebugger) + { + _ = Debugger.Launch(); + } -var analyzerPaths = new DirectoryInfo(AppContext.BaseDirectory).GetFiles("*.dll") - .Where(f => f.Name.StartsWith("Microsoft.CodeAnalysis.", StringComparison.Ordinal) && !f.Name.Contains("LanguageServer", StringComparison.Ordinal)) - .Select(f => f.FullName) - .ToImmutableArray(); + // Before we initialize the LSP server we can't send LSP log messages. + // Create a console logger as a fallback to use before the LSP server starts. + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.SetMinimumLevel(minimumLogLevel); + builder.AddProvider(new LspLogMessageLoggerProvider(fallbackLoggerFactory: + // Add a console logger as a fallback for when the LSP server has not finished initializing. + LoggerFactory.Create(builder => + { + builder.SetMinimumLevel(minimumLogLevel); + builder.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace); + }) + )); + }); + + // Register and load the appropriate MSBuild assemblies before we create the MEF composition. + // This is required because we need to include types from MS.CA.Workspaces.MSBuild which has a dependency on MSBuild dlls being loaded. + var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); + MSBuildLocator.RegisterInstance(msbuildInstances.First()); + + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + + // Immediately set the logger factory, so that way it'll be available for the rest of the composition + exportProvider.GetExportedValue().SetFactory(loggerFactory); + + // Cancellation token source that we can use to cancel on either LSP server shutdown (managed by client) or interrupt. + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + cancellationToken = cancellationTokenSource.Token; + + var bridgeCompletionTask = Task.CompletedTask; + if (brokeredServicePipeName != null) + { + var container = await BrokeredServiceContainer.CreateAsync(exportProvider, cancellationToken); -await projectSystem.InitializeSolutionLevelAnalyzersAsync(analyzerPaths); + var bridgeProvider = exportProvider.GetExportedValue(); -var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); -server.Start(); + bridgeCompletionTask = bridgeProvider.SetupBrokeredServicesBridgeAsync(brokeredServicePipeName, container, cancellationToken); + } -projectSystem.OpenSolution(solutionPath); + // Create the project system first, since right now the language server will assume there's at least one Workspace + var projectSystem = exportProvider.GetExportedValue(); -if (brokeredServicePipeName != null) -{ - await exportProvider.GetExportedValue().SayHelloToRemoteServerAsync(CancellationToken.None); -} + var analyzerPaths = new DirectoryInfo(AppContext.BaseDirectory).GetFiles("*.dll") + .Where(f => f.Name.StartsWith("Microsoft.CodeAnalysis.", StringComparison.Ordinal) && !f.Name.Contains("LanguageServer", StringComparison.Ordinal)) + .Select(f => f.FullName) + .ToImmutableArray(); -await server.WaitForExitAsync(); + await projectSystem.InitializeSolutionLevelAnalyzersAsync(analyzerPaths); -await bridgeCompletionTask; + var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); + server.Start(); -return; + projectSystem.OpenSolution(solutionPath); -static LogLevel GetLogLevel(string[] args) -{ - var logLevel = GetArgumentValue(args, "--logLevel"); - if (logLevel != null) + if (brokeredServicePipeName != null) { - return logLevel switch - { - "off" => LogLevel.None, - "minimal" => LogLevel.Information, - "messages" => LogLevel.Debug, - "verbose" => LogLevel.Trace, - _ => throw new InvalidOperationException($"Unexpected logLevel argument {logLevel}"), - }; + await exportProvider.GetExportedValue().SayHelloToRemoteServerAsync(cancellationToken); } - return LogLevel.Information; -} + await server.WaitForExitAsync(); + // Server has exited, cancel our token. + cancellationTokenSource.Cancel(); -static void LaunchDebuggerIfEnabled(string[] args) -{ - if (args.Contains("--debug") && !Debugger.IsAttached) - { - _ = Debugger.Launch(); - } -} + await bridgeCompletionTask; -static string GetSolutionPath(string[] args) -{ - return GetArgumentValue(args, "--solutionPath") ?? throw new InvalidOperationException($"Missing valid --solutionPath argument, got {string.Join(",", args)}"); + return; } -static string? GetBrokeredServicePipeName(string[] args) +static Parser CreateCommandLineParser() { - return GetArgumentValue(args, "--brokeredServicePipeName"); -} + var debugOption = new Option("--debug", getDefaultValue: () => false) + { + Description = "Flag indicating if the debugger should be launched on startup.", + IsRequired = false, + }; + var solutionPathOption = new Option("--solutionPath") + { + Description = "The solution path to initialize the server with.", + IsRequired = true, + }; + var brokeredServicePipeNameOption = new Option("--brokeredServicePipeName") + { + Description = "The name of the pipe used to connect to a remote process (if one exists).", + IsRequired = false, + }; + var logLevelOption = new Option("--logLevel", description: "The minimum log verbosity.", parseArgument: result => result.Tokens.Single().Value switch + { + "off" => LogLevel.None, + "minimal" => LogLevel.Information, + "messages" => LogLevel.Debug, + "verbose" => LogLevel.Trace, + _ => throw new InvalidOperationException($"Unexpected logLevel argument {result}"), + }) + { + IsRequired = true, + }; -static string? GetArgumentValue(string[] args, string argumentName) -{ - var argumentValueIndex = Array.IndexOf(args, argumentName) + 1; - if (argumentValueIndex > 0 && argumentValueIndex < args.Length) + var rootCommand = new RootCommand() { - return args[argumentValueIndex]; - } + debugOption, + solutionPathOption, + brokeredServicePipeNameOption, + logLevelOption, + }; + rootCommand.SetHandler(context => + { + var cancellationToken = context.GetCancellationToken(); + var launchDebugger = context.ParseResult.GetValueForOption(debugOption); + var solutionPath = context.ParseResult.GetValueForOption(solutionPathOption)!; + var brokeredServicePipeName = context.ParseResult.GetValueForOption(brokeredServicePipeNameOption); + var logLevel = context.ParseResult.GetValueForOption(logLevelOption); + + return RunAsync(launchDebugger, solutionPath, brokeredServicePipeName, logLevel, cancellationToken); + }); - return null; + return new CommandLineBuilder(rootCommand).UseDefaults().Build(); } From 4ef0d7adbb84b06851bbbddebeea83a78c239486 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Fri, 17 Feb 2023 18:41:57 -0800 Subject: [PATCH 038/261] Implement the IWorkspaceProjectFactoryService brokered service This is largely a passthrough implementation of the service that just forwards the calls to the ProjectSystemProject, which has basically the same structure. --- .../LanguageServer/Directory.Packages.props | 3 +- .../.editorconfig | 6 + .../BrokeredServiceProxy.cs | 68 ++++++ .../WorkspaceProjectFactoryServiceTests.cs | 51 +++++ .../BrokeredServiceBridgeManifestService.cs | 3 +- .../LanguageServerProjectSystem.cs | 15 +- .../HostWorkspace/WorkspaceProject.cs | 205 ++++++++++++++++++ .../WorkspaceProjectFactoryService.cs | 56 +++++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 1 + 9 files changed, 399 insertions(+), 9 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/BrokeredServiceProxy.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProject.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props index ef0958d4e29b6..fc7ad4650ed29 100644 --- a/src/Features/LanguageServer/Directory.Packages.props +++ b/src/Features/LanguageServer/Directory.Packages.props @@ -4,11 +4,12 @@ 17.4.0 1.5.5 - 4.6.0-2.23101.21 + 4.6.0-2.23125.2 $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) $(MicrosoftCodeAnalysisVersion) + $(MicrosoftCodeAnalysisVersion) 6.0.0 6.0.2 diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig new file mode 100644 index 0000000000000..51be17d793683 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig @@ -0,0 +1,6 @@ +# This file has specific settings for unit tests + +[*] + +# VSTHRD200: Use "Async" suffix in names of methods that return an awaitable type +dotnet_diagnostic.VSTHRD200.severity = none diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/BrokeredServiceProxy.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/BrokeredServiceProxy.cs new file mode 100644 index 0000000000000..bff88eebd4630 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/BrokeredServiceProxy.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Nerdbank.Streams; +using StreamJsonRpc; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + +/// +/// A wrapper which takes a service but actually sends calls to it through JsonRpc to ensure we can actually use the service across a wire. +/// +internal sealed class BrokeredServiceProxy : IAsyncDisposable where T : class +{ + /// + /// A task that cane awaited to assert the rest of the fields in this class being assigned and non-null. + /// + private readonly Task _createConnectionTask; + + private JsonRpc? _serverRpc; + private JsonRpc? _clientRpc; + private T? _clientFactoryProxy; + + public BrokeredServiceProxy(T service) + { + var (serverStream, clientStream) = FullDuplexStream.CreatePair(); + + var serverTask = Task.Run(async () => + { + var serverMultiplexingStream = await MultiplexingStream.CreateAsync(serverStream); + var serverChannel = await serverMultiplexingStream.AcceptChannelAsync(""); + + var serverFormatter = new MessagePackFormatter() { MultiplexingStream = serverMultiplexingStream }; + _serverRpc = new JsonRpc(new LengthHeaderMessageHandler(serverChannel, serverFormatter)); + + _serverRpc.AddLocalRpcTarget(service, options: null); + _serverRpc.StartListening(); + }); + + var clientTask = Task.Run(async () => + { + var clientMultiplexingStream = await MultiplexingStream.CreateAsync(clientStream); + var clientChannel = await clientMultiplexingStream.OfferChannelAsync(""); + + var clientFormatter = new MessagePackFormatter() { MultiplexingStream = clientMultiplexingStream }; + _clientRpc = new JsonRpc(new LengthHeaderMessageHandler(clientChannel, clientFormatter)); + + _clientFactoryProxy = _clientRpc.Attach(); + _clientRpc.StartListening(); + }); + + _createConnectionTask = Task.WhenAll(serverTask, clientTask); + } + + public async ValueTask DisposeAsync() + { + await _createConnectionTask; + + _serverRpc!.Dispose(); + _clientRpc!.Dispose(); + } + + public async Task GetServiceAsync() + { + await _createConnectionTask; + return _clientFactoryProxy!; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs new file mode 100644 index 0000000000000..778874e72e428 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; +using Microsoft.CodeAnalysis.LanguageServer.Logging; +using Microsoft.CodeAnalysis.Remote.ProjectSystem; +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; +public class WorkspaceProjectFactoryServiceTests +{ + [Fact] + public async Task CreateProjectAndBatch() + { + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + exportProvider.GetExportedValue().SetFactory(new LoggerFactory()); + + var projectSystem = exportProvider.GetExportedValue(); + + await using var brokeredServiceFactory = new BrokeredServiceProxy( + new WorkspaceProjectFactoryService(projectSystem)); + + var workspaceProjectFactoryService = await brokeredServiceFactory.GetServiceAsync(); + using var workspaceProject = await workspaceProjectFactoryService.CreateAndAddProjectAsync( + new WorkspaceProjectCreationInfo(LanguageNames.CSharp, "DisplayName", FilePath: null, new Dictionary()), + CancellationToken.None); + + using var batch = await workspaceProject.StartBatchAsync(CancellationToken.None); + + var sourceFilePath = MakeAbsolutePath("SourceFile.cs"); + var additionalFilePath = MakeAbsolutePath("AdditionalFile.txt"); + + await workspaceProject.AddSourceFilesAsync(new[] { new SourceFileInfo(sourceFilePath, Array.Empty()) }, CancellationToken.None); + await workspaceProject.AddAdditionalFilesAsync(new[] { additionalFilePath }, CancellationToken.None); + await batch.ApplyAsync(CancellationToken.None); + + // Verify it actually did something; we won't exclusively test each method since those are tested at lower layers + var project = projectSystem.Workspace.CurrentSolution.Projects.Single(); + Assert.Equal(sourceFilePath, project.Documents.Single().FilePath); + Assert.Equal(additionalFilePath, project.AdditionalDocuments.Single().FilePath); + } + + private static string MakeAbsolutePath(string relativePath) + { + if (OperatingSystem.IsWindows()) + return Path.Combine("Z:\\", relativePath); + else + return Path.Combine("//", relativePath); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs index 551b2dc7b0724..6e642bbc4b479 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs @@ -34,7 +34,8 @@ public ValueTask> GetAvailableServicesAsync( { return ValueTask.FromResult((IReadOnlyCollection)_container.GetRegisteredServices() .Select(s => s.Key) - .Where(s => s.Name.StartsWith("Microsoft.CodeAnalysis.LanguageServer", StringComparison.Ordinal)) + .Where(s => s.Name.StartsWith("Microsoft.CodeAnalysis.LanguageServer.", StringComparison.Ordinal) || + s.Name.StartsWith("Microsoft.VisualStudio.LanguageServices.", StringComparison.Ordinal)) .ToImmutableArray()); } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index 22309bbe8c580..26d5b2db2adc0 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -25,10 +25,8 @@ namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; internal sealed class LanguageServerProjectSystem { private readonly ILogger _logger; - private readonly ProjectSystemProjectFactory _projectSystemProjectFactory; private readonly ProjectFileLoaderRegistry _projectFileLoaderRegistry; private readonly AsyncBatchingWorkQueue _projectsToLoadAndReload; - private readonly ProjectSystemHostInfo _projectHostInfo; private readonly IFileChangeWatcher _fileChangeWatcher; /// @@ -42,7 +40,7 @@ public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VS { _logger = loggerFactory.CreateLogger(nameof(LanguageServerProjectSystem)); Workspace = new LanguageServerWorkspace(hostServicesProvider.HostServices); - _projectSystemProjectFactory = new ProjectSystemProjectFactory(Workspace, new FileChangeWatcher(), static _ => { }, _ => { }); + ProjectSystemProjectFactory = new ProjectSystemProjectFactory(Workspace, new FileChangeWatcher(), static (_, _) => Task.CompletedTask, _ => { }); analyzerLoader.InitializeDiagnosticsServices(Workspace); @@ -57,7 +55,7 @@ public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VS CancellationToken.None); // TODO: do we need to introduce a shutdown cancellation token for this? // TODO: fill this out - _projectHostInfo = new ProjectSystemHostInfo( + ProjectSystemHostInfo = new ProjectSystemHostInfo( DynamicFileInfoProviders: ImmutableArray>.Empty, null!, null!); @@ -66,6 +64,9 @@ public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VS public Workspace Workspace { get; } + public ProjectSystemProjectFactory ProjectSystemProjectFactory { get; } + public ProjectSystemHostInfo ProjectSystemHostInfo { get; } + public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray analyzerPaths) { var references = new List(); @@ -84,7 +85,7 @@ public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray a } } - await _projectSystemProjectFactory.ApplyChangeToWorkspaceAsync(w => w.SetCurrentSolution(s => s.WithAnalyzerReferences(references), WorkspaceChangeKind.SolutionChanged)); + await ProjectSystemProjectFactory.ApplyChangeToWorkspaceAsync(w => w.SetCurrentSolution(s => s.WithAnalyzerReferences(references), WorkspaceChangeKind.SolutionChanged)); } public void OpenSolution(string solutionFilePath) @@ -157,11 +158,11 @@ private async Task LoadOrReloadProjectAsync(string projectPath, ProjectBuildMana var projectSystemName = $"{projectPath} (${loadedProjectInfo.TargetFramework})"; var projectCreationInfo = new ProjectSystemProjectCreationInfo { AssemblyName = projectSystemName, FilePath = projectPath }; - var projectSystemProject = await _projectSystemProjectFactory.CreateAndAddToWorkspaceAsync( + var projectSystemProject = await ProjectSystemProjectFactory.CreateAndAddToWorkspaceAsync( projectSystemName, loadedProjectInfo.Language, projectCreationInfo, - _projectHostInfo); + ProjectSystemHostInfo); var loadedProject = new LoadedProject(projectSystemProject, Workspace.Services.SolutionServices, _fileChangeWatcher); loadedProject.NeedsReload += (_, _) => _projectsToLoadAndReload.AddWork(projectPath); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProject.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProject.cs new file mode 100644 index 0000000000000..e619df9bd8a48 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProject.cs @@ -0,0 +1,205 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Remote.ProjectSystem; +using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +internal class WorkspaceProject : IWorkspaceProject +{ + private readonly ProjectSystemProject _project; + private readonly ProjectSystemProjectOptionsProcessor _optionsProcessor; + + public WorkspaceProject(ProjectSystemProject project, SolutionServices solutionServices) + { + _project = project; + _optionsProcessor = new ProjectSystemProjectOptionsProcessor(_project, solutionServices); + } + + public async Task AddAdditionalFilesAsync(IReadOnlyList additionalFilePaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var additionalFilePath in additionalFilePaths) + _project.AddAdditionalFile(additionalFilePath); + } + + public async Task AddAnalyzerConfigFilesAsync(IReadOnlyList analyzerConfigPaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var analyzerConfigPath in analyzerConfigPaths) + _project.AddAnalyzerConfigFile(analyzerConfigPath); + } + + public async Task AddAnalyzerReferencesAsync(IReadOnlyList analyzerPaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var analyzerPath in analyzerPaths) + _project.AddAnalyzerReference(analyzerPath); + } + + public async Task AddDynamicFilesAsync(IReadOnlyList dynamicFilePaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var dynamicFilePath in dynamicFilePaths) + _project.AddDynamicSourceFile(dynamicFilePath, folders: ImmutableArray.Empty); + } + + public async Task AddMetadataReferencesAsync(IReadOnlyList metadataReferences, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var metadataReference in metadataReferences) + _project.AddMetadataReference(metadataReference.FilePath, metadataReference.CreateProperties()); + } + + public async Task AddSourceFilesAsync(IReadOnlyList sourceFiles, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var sourceFile in sourceFiles) + _project.AddSourceFile(sourceFile.FilePath, folders: sourceFile.FolderNames.ToImmutableArray()); + } + + public void Dispose() + { + _project.RemoveFromWorkspace(); + } + + public async Task RemoveAdditionalFilesAsync(IReadOnlyList additionalFilePaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var additionalFilePath in additionalFilePaths) + _project.RemoveAdditionalFile(additionalFilePath); + } + + public async Task RemoveAnalyzerConfigFilesAsync(IReadOnlyList analyzerConfigPaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var analyzerConfigPath in analyzerConfigPaths) + _project.RemoveAnalyzerConfigFile(analyzerConfigPath); + } + + public async Task RemoveAnalyzerReferencesAsync(IReadOnlyList analyzerPaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var analyzerPath in analyzerPaths) + _project.RemoveAnalyzerReference(analyzerPath); + } + + public async Task RemoveDynamicFilesAsync(IReadOnlyList dynamicFilePaths, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var dynamicFilePath in dynamicFilePaths) + _project.RemoveDynamicSourceFile(dynamicFilePath); + } + + public async Task RemoveMetadataReferencesAsync(IReadOnlyList metadataReferences, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var metadataReference in metadataReferences) + _project.RemoveMetadataReference(metadataReference.FilePath, metadataReference.CreateProperties()); + } + + public async Task RemoveSourceFilesAsync(IReadOnlyList sourceFiles, CancellationToken _) + { + await using var batchScope = _project.CreateBatchScope(); + + foreach (var sourceFile in sourceFiles) + _project.RemoveSourceFile(sourceFile); + } + + public async Task SetBuildSystemPropertiesAsync(IReadOnlyDictionary properties, CancellationToken _) + { + // Create a batch scope, just so we have asynchronous closing and application of the batch. + await using var batchScope = _project.CreateBatchScope(); + + foreach (var (name, value) in properties) + { + var valueOrNull = string.IsNullOrEmpty(value) ? null : value; + + switch (name) + { + case "AssemblyName": _project.AssemblyName = value; break; + case "MaxSupportedLangVersion": _project.MaxLangVersion = value; break; + case "RootNamespace": _project.DefaultNamespace = valueOrNull; break; + case "RunAnalyzers": _project.RunAnalyzers = bool.Parse(valueOrNull ?? bool.TrueString); break; + case "RunAnalyzersDuringLiveAnalysis": _project.RunAnalyzersDuringLiveAnalysis = bool.Parse(valueOrNull ?? bool.TrueString); break; + case "TargetPath": _project.OutputFilePath = GetFullyQualifiedPath(valueOrNull); break; + case "TargetRefPath": _project.OutputRefFilePath = GetFullyQualifiedPath(valueOrNull); break; + } + } + + string? GetFullyQualifiedPath(string? propertyValue) + { + Contract.ThrowIfNull(_project.FilePath, "We don't have a project path at this point."); + + if (propertyValue is not null) + return Path.Combine(_project.FilePath, propertyValue); + else + return null; + } + } + + public async Task SetCommandLineArgumentsAsync(IReadOnlyList arguments, CancellationToken _) + { + // Create a batch scope, just so we have asynchronous closing and application of the batch. + await using var batchScope = _project.CreateBatchScope(); + _optionsProcessor.SetCommandLine(arguments.ToImmutableArray()); + } + + public async Task SetDisplayNameAsync(string displayName, CancellationToken _) + { + // Create a batch scope, just so we have asynchronous closing and application of the batch. + await using var batchScope = _project.CreateBatchScope(); + _project.DisplayName = displayName; + } + + public async Task SetProjectHasAllInformationAsync(bool hasAllInformation, CancellationToken _) + { + // Create a batch scope, just so we have asynchronous closing and application of the batch. + await using var batchScope = _project.CreateBatchScope(); + _project.HasAllInformation = hasAllInformation; + } + + public Task StartBatchAsync(CancellationToken cancellationToken) + { + return Task.FromResult(new WorkspaceProjectBatch(_project.CreateBatchScope())); + } + + private class WorkspaceProjectBatch : IWorkspaceProjectBatch + { + private IAsyncDisposable? _batch; + + public WorkspaceProjectBatch(IAsyncDisposable batch) + { + _batch = batch; + } + + public async Task ApplyAsync(CancellationToken cancellationToken) + { + if (_batch == null) + throw new InvalidOperationException("The batch has already been applied."); + + await _batch.DisposeAsync().ConfigureAwait(false); + _batch = null; + } + + public void Dispose() + { + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs new file mode 100644 index 0000000000000..93880ab12ef3e --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Remote.ProjectSystem; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Shell.ServiceBroker; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +/// +/// An implementation of the brokered service that just maps calls to the underlying project system. +/// +[ExportBrokeredService("Microsoft.VisualStudio.LanguageServices.WorkspaceProjectFactoryService", null, Audience = ServiceAudience.Local)] +internal class WorkspaceProjectFactoryService : IWorkspaceProjectFactoryService, IExportedBrokeredService +{ + private readonly LanguageServerProjectSystem _projectSystem; + + [ImportingConstructor] + public WorkspaceProjectFactoryService(LanguageServerProjectSystem projectSystem) + { + _projectSystem = projectSystem; + } + + ServiceRpcDescriptor IExportedBrokeredService.Descriptor => WorkspaceProjectFactoryServiceDescriptor.ServiceDescriptor; + + Task IExportedBrokeredService.InitializeAsync(CancellationToken cancellationToken) + { + // There's nothing to initialize + return Task.CompletedTask; + } + + public async Task CreateAndAddProjectAsync(WorkspaceProjectCreationInfo creationInfo, CancellationToken _) + { + var project = await _projectSystem.ProjectSystemProjectFactory.CreateAndAddToWorkspaceAsync( + creationInfo.DisplayName, + creationInfo.Language, + new Workspaces.ProjectSystem.ProjectSystemProjectCreationInfo { FilePath = creationInfo.FilePath }, + _projectSystem.ProjectSystemHostInfo); + + var workspaceProject = new WorkspaceProject(project, _projectSystem.Workspace.Services.SolutionServices); + + // We've created a new project, so initialize properties we have + await workspaceProject.SetBuildSystemPropertiesAsync(creationInfo.BuildSystemProperties, CancellationToken.None); + + return workspaceProject; + } + + public Task> GetSupportedBuildSystemPropertiesAsync(CancellationToken _) + { + // TODO: implement + return Task.FromResult((IReadOnlyCollection)ImmutableArray.Empty); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 3f80a939e1852..c3883aac60ea9 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -22,6 +22,7 @@ + From f7a7f09c478d57d462e36522567f818d9d566bb2 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Thu, 23 Feb 2023 17:05:33 -0800 Subject: [PATCH 039/261] Only require a solution to load if we don't have an external project system --- .../Program.cs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 6bfbfbd756205..35a9b638f3a5c 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -20,7 +20,7 @@ var parser = CreateCommandLineParser(); return await parser.InvokeAsync(args); -static async Task RunAsync(bool launchDebugger, string solutionPath, string? brokeredServicePipeName, LogLevel minimumLogLevel, CancellationToken cancellationToken) +static async Task RunAsync(bool launchDebugger, string? solutionPath, string? brokeredServicePipeName, LogLevel minimumLogLevel, CancellationToken cancellationToken) { if (launchDebugger) { @@ -44,7 +44,14 @@ static async Task RunAsync(bool launchDebugger, string solutionPath, string? bro // Register and load the appropriate MSBuild assemblies before we create the MEF composition. // This is required because we need to include types from MS.CA.Workspaces.MSBuild which has a dependency on MSBuild dlls being loaded. - var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = Path.GetDirectoryName(solutionPath) }); + var msbuildDiscoveryOptions = new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk }; + + // TODO: we probably shouldn't be doing any discovery if we don't have a solution to load, but for now we'll ensure we still have it since we indirectly + // depend on parts of MSBuildWorkspace + if (solutionPath != null) + msbuildDiscoveryOptions.WorkingDirectory = Path.GetDirectoryName(solutionPath); + + var msbuildInstances = MSBuildLocator.QueryVisualStudioInstances(msbuildDiscoveryOptions); MSBuildLocator.RegisterInstance(msbuildInstances.First()); using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); @@ -79,7 +86,10 @@ static async Task RunAsync(bool launchDebugger, string solutionPath, string? bro var server = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, loggerFactory.CreateLogger(nameof(LanguageServerHost))); server.Start(); - projectSystem.OpenSolution(solutionPath); + if (solutionPath != null) + { + projectSystem.OpenSolution(solutionPath); + } if (brokeredServicePipeName != null) { @@ -102,10 +112,10 @@ static Parser CreateCommandLineParser() Description = "Flag indicating if the debugger should be launched on startup.", IsRequired = false, }; - var solutionPathOption = new Option("--solutionPath") + var solutionPathOption = new Option("--solutionPath") { Description = "The solution path to initialize the server with.", - IsRequired = true, + IsRequired = false, }; var brokeredServicePipeNameOption = new Option("--brokeredServicePipeName") { @@ -135,7 +145,7 @@ static Parser CreateCommandLineParser() { var cancellationToken = context.GetCancellationToken(); var launchDebugger = context.ParseResult.GetValueForOption(debugOption); - var solutionPath = context.ParseResult.GetValueForOption(solutionPathOption)!; + var solutionPath = context.ParseResult.GetValueForOption(solutionPathOption); var brokeredServicePipeName = context.ParseResult.GetValueForOption(brokeredServicePipeNameOption); var logLevel = context.ParseResult.GetValueForOption(logLevelOption); From 9a379619599ef959e3c9b622c9a12dbd90444ab1 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 28 Feb 2023 13:37:19 -0800 Subject: [PATCH 040/261] Fix exception thrown if we are removing an analyzer reference --- .../HostDiagnosticAnalyzerProvider.cs | 17 ++++++++++ .../LanguageServerProjectSystem.cs | 5 ++- .../ProjectSystemDiagnosticSource.cs | 32 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostDiagnosticAnalyzerProvider.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectSystemDiagnosticSource.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostDiagnosticAnalyzerProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostDiagnosticAnalyzerProvider.cs new file mode 100644 index 0000000000000..8bbe02aa13604 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/HostDiagnosticAnalyzerProvider.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; +internal class HostDiagnosticAnalyzerProvider : IHostDiagnosticAnalyzerProvider +{ + public ImmutableArray<(AnalyzerFileReference reference, string extensionId)> GetAnalyzerReferencesInExtensions() + { + // Right now we don't expose any way for the extensions in VS Code to provide analyzer references. + return ImmutableArray<(AnalyzerFileReference reference, string extensionId)>.Empty; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index 26d5b2db2adc0..c818520a6db28 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -54,11 +54,10 @@ public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VS listenerProvider.GetListener(FeatureAttribute.Workspace), CancellationToken.None); // TODO: do we need to introduce a shutdown cancellation token for this? - // TODO: fill this out ProjectSystemHostInfo = new ProjectSystemHostInfo( DynamicFileInfoProviders: ImmutableArray>.Empty, - null!, - null!); + new ProjectSystemDiagnosticSource(), + new HostDiagnosticAnalyzerProvider()); _fileChangeWatcher = fileChangeWatcher; } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectSystemDiagnosticSource.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectSystemDiagnosticSource.cs new file mode 100644 index 0000000000000..57a11e0431565 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectSystemDiagnosticSource.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; +internal class ProjectSystemDiagnosticSource : IProjectSystemDiagnosticSource +{ + public void ClearAllDiagnosticsForProject(ProjectId projectId) + { + } + + public void ClearAnalyzerReferenceDiagnostics(AnalyzerFileReference fileReference, string language, ProjectId projectId) + { + } + + public void ClearDiagnosticsForProject(ProjectId projectId, object key) + { + } + + public DiagnosticData CreateAnalyzerLoadFailureDiagnostic(AnalyzerLoadFailureEventArgs e, string fullPath, ProjectId projectId, string language) + { + return DocumentAnalysisExecutor.CreateAnalyzerLoadFailureDiagnostic(e, fullPath, projectId, language); + } + + public void UpdateDiagnosticsForProject(ProjectId projectId, object key, IEnumerable items) + { + // TODO: actually store the diagnostics + } +} From 3a2e5d58139d86ab3b7ce32669709324f3df7ddc Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 28 Feb 2023 14:35:57 -0800 Subject: [PATCH 041/261] Deduplicate references that might come from the commmand arguments This matches the more or less equivalent change in Roslyn we did in https://github.com/dotnet/roslyn/pull/58701. --- .../HostWorkspace/LoadedProject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs index 8d0db9004347c..2b3ed31a4bb33 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs @@ -93,7 +93,7 @@ public async ValueTask UpdateWithNewProjectInfoAsync(ProjectFileInfo newProjectI document => _projectSystemProject.AddSourceFile(document.FilePath), document => _projectSystemProject.RemoveSourceFile(document.FilePath)); - var metadataReferences = _optionsProcessor.GetParsedCommandLineArguments().MetadataReferences; + var metadataReferences = _optionsProcessor.GetParsedCommandLineArguments().MetadataReferences.Distinct(); UpdateProjectSystemProjectCollection( metadataReferences, From 8ffdca3ece9a6f9e7b0ff89f719a2c953f7f1f0a Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 1 Mar 2023 11:33:34 -0800 Subject: [PATCH 042/261] Run on correct pools --- azure-pipelines.yml | 144 +++++++++++++++--- eng/build.ps1 | 5 + eng/build.sh | 10 ++ eng/pipelines/build-unix-job.yml | 5 +- eng/pipelines/build-windows-job.yml | 5 +- eng/pipelines/checkout-unix-task.yml | 34 +++-- eng/pipelines/checkout-windows-task.yml | 34 +++-- eng/pipelines/evaluate-changed-files.yml | 19 +-- .../test-unix-job-single-machine.yml | 5 +- eng/pipelines/test-unix-job.yml | 7 +- .../test-windows-job-single-machine.yml | 5 +- eng/pipelines/test-windows-job.yml | 7 +- src/Tools/Source/RunTests/Options.cs | 9 ++ src/Tools/Source/RunTests/TestRunner.cs | 16 +- 14 files changed, 246 insertions(+), 59 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a5b33e23a22e6..16ba36cf75a1b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -29,6 +29,10 @@ pr: - CONTRIBUTING.md - README.md +variables: + HelixApiAccessToken: '' + + stages: - stage: Windows_Debug_Build dependsOn: [] @@ -38,7 +42,10 @@ stages: jobName: Build_Windows_Debug testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug - queueName: windows.vs2022preview.amd64.open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + queueName: windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + queueName: windows.vs2022preview.amd64 restoreArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false buildArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false @@ -50,7 +57,10 @@ stages: jobName: Build_Windows_Release testArtifactName: Transport_Artifacts_Windows_Release configuration: Release - queueName: windows.vs2022preview.amd64.open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + queueName: windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + queueName: windows.vs2022preview.amd64 restoreArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false buildArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false @@ -62,7 +72,10 @@ stages: jobName: Build_Unix_Debug testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug - queueName: Build.Ubuntu.1804.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + queueName: Build.Ubuntu.1804.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + queueName: Build.Ubuntu.1804.Amd64 - stage: Source_Build dependsOn: [] @@ -71,6 +84,9 @@ stages: - stage: Windows_Debug_Desktop dependsOn: Windows_Debug_Build + variables: + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-HelixApi-Access jobs: - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-windows-job.yml @@ -80,6 +96,11 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testDesktop -testArch x86 + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - template: eng/pipelines/test-windows-job.yml parameters: @@ -88,9 +109,17 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testDesktop -testArch x64 + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - stage: Windows_Release_Desktop dependsOn: Windows_Release_Build + variables: + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-HelixApi-Access jobs: - template: eng/pipelines/test-windows-job.yml parameters: @@ -99,6 +128,11 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testDesktop -testArch x86 + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-windows-job.yml @@ -108,6 +142,11 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testDesktop -testArch x64 + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - template: eng/pipelines/test-windows-job.yml parameters: @@ -115,10 +154,18 @@ stages: jobName: Test_Windows_Desktop_Spanish_Release_64 testArtifactName: Transport_Artifacts_Windows_Release configuration: Release - testArguments: -testDesktop -testArch x64 -helixQueueName Windows.10.Amd64.Server2022.ES.Open + testArguments: -testDesktop -testArch x64 + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Server2022.ES.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Server2022.ES + helixApiAccessToken: $(HelixApiAccessToken) - stage: Windows_Debug_CoreClr dependsOn: Windows_Debug_Build + variables: + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-HelixApi-Access jobs: - template: eng/pipelines/test-windows-job.yml parameters: @@ -127,6 +174,11 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testCoreClr + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-windows-job-single-machine.yml @@ -135,6 +187,10 @@ stages: jobName: Test_Windows_CoreClr_Debug_Single_Machine testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug + ${{ if eq(variables['System.TeamProject'], 'public') }}: + queueName: windows.vs2022.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + queueName: windows.vs2022.amd64 testArguments: -testCoreClr - template: eng/pipelines/test-windows-job.yml @@ -144,6 +200,11 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testCoreClr -testIOperation -testCompilerOnly + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) # This leg runs almost all the compiler tests supported on CoreCLR, but # with additional validation for used assemblies and GetEmitDiagnostics @@ -154,9 +215,17 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testCoreClr -testUsedAssemblies -testCompilerOnly + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - stage: Windows_Release_CoreClr dependsOn: Windows_Release_Build + variables: + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-HelixApi-Access jobs: - template: eng/pipelines/test-windows-job.yml parameters: @@ -165,9 +234,17 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testCoreClr + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Windows.10.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - stage: Unix_Debug_CoreClr dependsOn: Unix_Build + variables: + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-HelixApi-Access jobs: - template: eng/pipelines/test-unix-job.yml parameters: @@ -175,7 +252,12 @@ stages: jobName: Test_Linux_Debug testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug - testArguments: --testCoreClr --helixQueueName Ubuntu.1804.Amd64.Open + testArguments: --testCoreClr + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: Ubuntu.1804.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: Ubuntu.1804.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-unix-job-single-machine.yml @@ -185,7 +267,10 @@ stages: testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug testArguments: --testCoreClr - queueName: Build.Ubuntu.1804.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + queueName: Build.Ubuntu.1804.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + queueName: Build.Ubuntu.1804.Amd64 - template: eng/pipelines/test-unix-job.yml parameters: @@ -193,7 +278,12 @@ stages: jobName: Test_macOS_Debug testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug - testArguments: --testCoreClr --helixQueueName OSX.1015.Amd64.Open + testArguments: --testCoreClr + ${{ if eq(variables['System.TeamProject'], 'public') }}: + helixQueueName: OSX.1015.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + helixQueueName: OSX.1015.Amd64 + helixApiAccessToken: $(HelixApiAccessToken) - stage: Correctness dependsOn: [] @@ -213,8 +303,12 @@ stages: - job: Correctness_Build_Artifacts dependsOn: Determine_Changes pool: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals windows.vs2022preview.amd64 timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -263,8 +357,12 @@ stages: dependsOn: Determine_Changes condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(dependencies.Determine_Changes.outputs['SetPathVars_compilers.containsChange'], 'true')) pool: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals windows.vs2022preview.amd64 timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -285,8 +383,12 @@ stages: dependsOn: Determine_Changes condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(dependencies.Determine_Changes.outputs['SetPathVars_compilers.containsChange'], 'true')) pool: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals windows.vs2022preview.amd64 timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -331,8 +433,12 @@ stages: dependsOn: Determine_Changes condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(dependencies.Determine_Changes.outputs['SetPathVars_compilers.containsChange'], 'true')) pool: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + demands: ImageOverride -equals windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals windows.vs2022preview.amd64 timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -360,8 +466,12 @@ stages: - job: Correctness_Analyzers pool: - name: NetCore-Public - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 timeoutInMinutes: 35 variables: - template: eng/pipelines/variables-build.yml diff --git a/eng/build.ps1 b/eng/build.ps1 index bbfded1f1f115..6c03c48b13895 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -67,6 +67,7 @@ param ( [switch]$sequential, [switch]$helix, [string]$helixQueueName = "", + [string]$helixApiAccessToken = "", [parameter(ValueFromRemainingArguments=$true)][string[]]$properties) @@ -455,6 +456,10 @@ function TestUsingRunTests() { $args += " --helixQueueName $helixQueueName" } + if ($helixApiAccessToken) { + $args += " --helixApiAccessToken $helixApiAccessToken" + } + try { Write-Host "$runTests $args" Exec-Console $dotnetExe "$runTests $args" diff --git a/eng/build.sh b/eng/build.sh index d49ebf7de670b..c160b5e887752 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -68,6 +68,7 @@ binary_log=false ci=false helix=false helix_queue_name="" +helix_api_access_token="" bootstrap=false run_analyzers=false skip_documentation=false @@ -140,6 +141,11 @@ while [[ $# > 0 ]]; do args="$args $1" shift ;; + --helixapiaccesstoken) + helix_api_access_token=$2 + args="$args $1" + shift + ;; --bootstrap) bootstrap=true # Bootstrap requires restore @@ -320,6 +326,10 @@ if [[ "$test_core_clr" == true ]]; then runtests_args="$runtests_args --helixQueueName $helix_queue_name" fi + if [[ -n "$helix_api_access_token" ]]; then + runtests_args="$runtests_args --helixApiAccessToken $helix_api_access_token" + fi + if [[ "$helix" == true ]]; then runtests_args="$runtests_args --helix" fi diff --git a/eng/pipelines/build-unix-job.yml b/eng/pipelines/build-unix-job.yml index 20bbe8f070684..6551a8a5f3b9a 100644 --- a/eng/pipelines/build-unix-job.yml +++ b/eng/pipelines/build-unix-job.yml @@ -20,7 +20,10 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - name: NetCore-Public + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index 606ec1c431bbf..9776ace7e3184 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -26,7 +26,10 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - name: NetCore-Public + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/checkout-unix-task.yml b/eng/pipelines/checkout-unix-task.yml index e65175caf5a7d..0496d30b3d275 100644 --- a/eng/pipelines/checkout-unix-task.yml +++ b/eng/pipelines/checkout-unix-task.yml @@ -1,14 +1,26 @@ # Shallow checkout sources on Unix +parameters: +- name: depth + type: number + default: 1 + steps: - - checkout: none - - - script: | - set -x - git init - git config --local checkout.workers 0 - git config --local fetch.parallel 0 - git remote add origin "$(Build.Repository.Uri)" - git fetch --no-tags --no-auto-maintenance --depth=1 origin "$(Build.SourceVersion)" - git checkout "$(Build.SourceVersion)" - displayName: Shallow Checkout + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - checkout: none + + - script: | + set -x + git init + git config --local checkout.workers 0 + git config --local fetch.parallel 0 + git remote add origin "$(Build.Repository.Uri)" + git fetch --no-tags --no-auto-maintenance --depth=${{ parameters.depth }} origin "$(Build.SourceVersion)" + git checkout "$(Build.SourceVersion)" + displayName: Shallow Checkout + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - checkout: self + fetchDepth: ${{ parameters.depth }} + fetchTags: false + + diff --git a/eng/pipelines/checkout-windows-task.yml b/eng/pipelines/checkout-windows-task.yml index 304aa7868a5f9..258a0b86d2dd3 100644 --- a/eng/pipelines/checkout-windows-task.yml +++ b/eng/pipelines/checkout-windows-task.yml @@ -1,16 +1,28 @@ # Shallow checkout sources on Windows +parameters: +- name: depth + type: number + default: 1 + # Git path based on https://github.com/microsoft/azure-pipelines-agent/blob/f98a479ab3cc323ff17b8cb75d5ab5f953f342cc/src/Agent.Plugins/GitCliManager.cs#L90 steps: - - checkout: none + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - checkout: none + + - script: | + set PATH=$(Agent.HomeDirectory)\externals\git\cmd;%PATH% + @echo on + git init + git config --local checkout.workers 0 + git config --local fetch.parallel 0 + git remote add origin "$(Build.Repository.Uri)" + git fetch --no-tags --no-auto-maintenance --depth=${{ parameters.depth }} origin "$(Build.SourceVersion)" + git checkout "$(Build.SourceVersion)" + displayName: Shallow Checkout + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - checkout: self + fetchDepth: ${{ parameters.depth }} + fetchTags: false - - script: | - set PATH=$(Agent.HomeDirectory)\externals\git\cmd;%PATH% - @echo on - git init - git config --local checkout.workers 0 - git config --local fetch.parallel 0 - git remote add origin "$(Build.Repository.Uri)" - git fetch --no-tags --no-auto-maintenance --depth=1 origin "$(Build.SourceVersion)" - git checkout "$(Build.SourceVersion)" - displayName: Shallow Checkout + diff --git a/eng/pipelines/evaluate-changed-files.yml b/eng/pipelines/evaluate-changed-files.yml index ff61d577afe38..df79c274cef53 100644 --- a/eng/pipelines/evaluate-changed-files.yml +++ b/eng/pipelines/evaluate-changed-files.yml @@ -17,7 +17,10 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - name: NetCore-Public + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: @@ -25,17 +28,9 @@ jobs: timeoutInMinutes: 10 steps: - - checkout: none - - - script: | - set -x - git init - git config --local checkout.workers 0 - git config --local fetch.parallel 0 - git remote add origin "$(Build.Repository.Uri)" - git fetch --no-tags --no-auto-maintenance --depth=2 origin "$(Build.SourceVersion)" - git checkout "$(Build.SourceVersion)" - displayName: Shallow Checkout + - template: checkout-unix-task.yml + parameters: + depth: 2 - ${{ if ne(parameters.paths[0], '') }}: - ${{ each path in parameters.paths }}: diff --git a/eng/pipelines/test-unix-job-single-machine.yml b/eng/pipelines/test-unix-job-single-machine.yml index 3656369a48294..3958c29569c49 100644 --- a/eng/pipelines/test-unix-job-single-machine.yml +++ b/eng/pipelines/test-unix-job-single-machine.yml @@ -26,7 +26,10 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - name: NetCore-Public + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/test-unix-job.yml b/eng/pipelines/test-unix-job.yml index 5b6729a8888dd..8358934293421 100644 --- a/eng/pipelines/test-unix-job.yml +++ b/eng/pipelines/test-unix-job.yml @@ -1,5 +1,7 @@ # Test on Unix using Helix parameters: +- name: helixQueueName + type: string - name: testRunName type: string default: '' @@ -15,6 +17,9 @@ parameters: - name: testArguments type: string default: '' +- name: helixApiAccessToken + type: string + default: '' jobs: - job: ${{ parameters.jobName }} @@ -43,7 +48,7 @@ jobs: - task: ShellScript@2 inputs: scriptPath: ./eng/build.sh - args: --ci --helix --configuration ${{ parameters.configuration }} ${{ parameters.testArguments }} + args: --ci --helix --configuration ${{ parameters.configuration }} --helixQueueName ${{ parameters.helixQueueName }} --helixApiAccessToken ${{ parameters.helixApiAccessToken }} ${{ parameters.testArguments }} displayName: Test env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) diff --git a/eng/pipelines/test-windows-job-single-machine.yml b/eng/pipelines/test-windows-job-single-machine.yml index c9cb180c47008..b11009a53acf8 100644 --- a/eng/pipelines/test-windows-job-single-machine.yml +++ b/eng/pipelines/test-windows-job-single-machine.yml @@ -22,7 +22,10 @@ parameters: jobs: - job: ${{ parameters.jobName }} pool: - name: NetCore-Public + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore-Public + ${{ if ne(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Internal demands: ImageOverride -equals ${{ parameters.queueName }} timeoutInMinutes: 120 variables: diff --git a/eng/pipelines/test-windows-job.yml b/eng/pipelines/test-windows-job.yml index 5484f13af74cf..6d4daba320b50 100644 --- a/eng/pipelines/test-windows-job.yml +++ b/eng/pipelines/test-windows-job.yml @@ -1,5 +1,7 @@ # Test on Windows Desktop using Helix parameters: +- name: helixQueueName + type: string - name: testRunName type: string default: '' @@ -15,6 +17,9 @@ parameters: - name: testArguments type: string default: '' +- name: helixApiAccessToken + type: string + default: '' jobs: - job: ${{ parameters.jobName }} @@ -44,7 +49,7 @@ jobs: displayName: Run Unit Tests inputs: filePath: eng/build.ps1 - arguments: -ci -helix -configuration ${{ parameters.configuration }} ${{ parameters.testArguments }} -collectDumps + arguments: -ci -helix -configuration ${{ parameters.configuration }} -helixQueueName ${{ parameters.helixQueueName }} -helixApiAccessToken ${{ parameters.helixApiAccessToken }} ${{ parameters.testArguments }} -collectDumps env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) diff --git a/src/Tools/Source/RunTests/Options.cs b/src/Tools/Source/RunTests/Options.cs index c2d4a47731523..d3ce7af3ed56d 100644 --- a/src/Tools/Source/RunTests/Options.cs +++ b/src/Tools/Source/RunTests/Options.cs @@ -87,6 +87,12 @@ internal class Options /// public string? HelixQueueName { get; set; } + /// + /// Access token to send jobs to helix (only valid when is ). + /// This should only be set when using internal helix queues. + /// + public string? HelixApiAccessToken { get; set; } + /// /// Path to the dotnet executable we should use for running dotnet test /// @@ -142,6 +148,7 @@ internal class Options var sequential = false; var helix = false; var helixQueueName = "Windows.10.Amd64.Open"; + string? helixApiAccessToken = null; var retry = false; string? testFilter = null; int? timeout = null; @@ -168,6 +175,7 @@ internal class Options { "sequential", "Run tests sequentially", o => sequential = o is object }, { "helix", "Run tests on Helix", o => helix = o is object }, { "helixQueueName=", "Name of the Helix queue to run tests on", (string s) => helixQueueName = s }, + { "helixApiAccessToken=", "Access token for internal helix queues", (string s) => helixApiAccessToken = s }, { "testfilter=", "xUnit string to pass to --filter, e.g. FullyQualifiedName~TestClass1|Category=CategoryA", (string s) => testFilter = s }, { "timeout=", "Minute timeout to limit the tests to", (int i) => timeout = i }, { "out=", "Test result file directory (when running on Helix, this is relative to the Helix work item directory)", (string s) => resultFileDirectory = s }, @@ -254,6 +262,7 @@ internal class Options Sequential = sequential, UseHelix = helix, HelixQueueName = helixQueueName, + HelixApiAccessToken = helixApiAccessToken, IncludeHtml = includeHtml, TestFilter = testFilter, Timeout = timeout is { } t ? TimeSpan.FromMinutes(t) : null, diff --git a/src/Tools/Source/RunTests/TestRunner.cs b/src/Tools/Source/RunTests/TestRunner.cs index 573174594f74a..4907b8db5a1b6 100644 --- a/src/Tools/Source/RunTests/TestRunner.cs +++ b/src/Tools/Source/RunTests/TestRunner.cs @@ -108,7 +108,6 @@ internal async Task RunAllOnHelixAsync(ImmutableArraytest " + buildNumber + @" " + _options.HelixQueueName + @" - " + queuedBy + @" true " + globalJson.sdk.version + @" sdk @@ -123,9 +122,22 @@ internal async Task RunAllOnHelixAsync(ImmutableArray { Debug.Assert(e.Data is not null); ConsoleUtil.WriteLine(e.Data); }, cancellationToken: cancellationToken); From 3c0e7d766560caf9766e723c93033cf231fc921c Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Mar 2023 11:09:28 -0800 Subject: [PATCH 043/261] Consolidate pool/queue variables --- azure-pipelines.yml | 203 +++++++++--------- eng/pipelines/build-unix-job.yml | 8 +- eng/pipelines/build-windows-job.yml | 8 +- eng/pipelines/checkout-unix-task.yml | 19 +- eng/pipelines/checkout-windows-task.yml | 20 +- eng/pipelines/evaluate-changed-files.yml | 8 +- .../test-unix-job-single-machine.yml | 8 +- .../test-windows-job-single-machine.yml | 8 +- 8 files changed, 122 insertions(+), 160 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 16ba36cf75a1b..d4635c54aafa1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -30,8 +30,59 @@ pr: - README.md variables: - HelixApiAccessToken: '' - + # This value is conditionally overriden by the variable group DotNet-HelixApi-Access. + # ADO only lets us conditionally include a variable group on individual stages. + - name: HelixApiAccessToken + value: '' + + # Set pool / queue name variables depending on which instance we're running in. + - name: PoolName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: NetCore-Public + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: NetCore1ESPool-Internal + + - name: Vs2022PreviewQueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: windows.vs2022preview.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: windows.vs2022preview.amd64 + + - name: Vs2022QueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: windows.vs2022.amd64.open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: windows.vs2022.amd64 + + - name: UbuntuQueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: Build.Ubuntu.1804.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: Build.Ubuntu.1804.Amd64 + + - name: HelixWindowsQueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: Windows.10.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: Windows.10.Amd64 + + - name: HelixWindowsSpanishQueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: Windows.10.Amd64.Server2022.ES.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: Windows.10.Amd64.Server2022.ES + + - name: HelixUbuntuQueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: Ubuntu.1804.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: Ubuntu.1804.Amd64 + + - name: HelixMacOsQueueName + ${{ if eq(variables['System.TeamProject'], 'public') }}: + value: OSX.1015.Amd64.Open + ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: OSX.1015.Amd64 stages: - stage: Windows_Debug_Build @@ -42,10 +93,8 @@ stages: jobName: Build_Windows_Debug testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug - ${{ if eq(variables['System.TeamProject'], 'public') }}: - queueName: windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - queueName: windows.vs2022preview.amd64 + poolName: $(PoolName) + queueName: $(Vs2022PreviewQueueName) restoreArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false buildArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false @@ -57,10 +106,8 @@ stages: jobName: Build_Windows_Release testArtifactName: Transport_Artifacts_Windows_Release configuration: Release - ${{ if eq(variables['System.TeamProject'], 'public') }}: - queueName: windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - queueName: windows.vs2022preview.amd64 + poolName: $(PoolName) + queueName: $(Vs2022PreviewQueueName) restoreArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false buildArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false @@ -72,10 +119,8 @@ stages: jobName: Build_Unix_Debug testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug - ${{ if eq(variables['System.TeamProject'], 'public') }}: - queueName: Build.Ubuntu.1804.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - queueName: Build.Ubuntu.1804.Amd64 + poolName: $(PoolName) + queueName: $(UbuntuQueueName) - stage: Source_Build dependsOn: [] @@ -96,11 +141,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testDesktop -testArch x86 - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - template: eng/pipelines/test-windows-job.yml parameters: @@ -109,11 +151,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testDesktop -testArch x64 - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - stage: Windows_Release_Desktop dependsOn: Windows_Release_Build @@ -128,11 +167,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testDesktop -testArch x86 - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-windows-job.yml @@ -142,11 +178,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testDesktop -testArch x64 - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - template: eng/pipelines/test-windows-job.yml parameters: @@ -155,11 +188,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testDesktop -testArch x64 - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Server2022.ES.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Server2022.ES - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsSpanishQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - stage: Windows_Debug_CoreClr dependsOn: Windows_Debug_Build @@ -174,11 +204,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testCoreClr - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-windows-job-single-machine.yml @@ -187,10 +214,8 @@ stages: jobName: Test_Windows_CoreClr_Debug_Single_Machine testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug - ${{ if eq(variables['System.TeamProject'], 'public') }}: - queueName: windows.vs2022.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - queueName: windows.vs2022.amd64 + poolName: $(PoolName) + queueName: $(Vs2022QueueName) testArguments: -testCoreClr - template: eng/pipelines/test-windows-job.yml @@ -200,11 +225,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testCoreClr -testIOperation -testCompilerOnly - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) # This leg runs almost all the compiler tests supported on CoreCLR, but # with additional validation for used assemblies and GetEmitDiagnostics @@ -215,11 +237,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Debug configuration: Debug testArguments: -testCoreClr -testUsedAssemblies -testCompilerOnly - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - stage: Windows_Release_CoreClr dependsOn: Windows_Release_Build @@ -234,11 +253,8 @@ stages: testArtifactName: Transport_Artifacts_Windows_Release configuration: Release testArguments: -testCoreClr - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Windows.10.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixWindowsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - stage: Unix_Debug_CoreClr dependsOn: Unix_Build @@ -253,11 +269,8 @@ stages: testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug testArguments: --testCoreClr - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: Ubuntu.1804.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: Ubuntu.1804.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixUbuntuQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - template: eng/pipelines/test-unix-job-single-machine.yml @@ -267,10 +280,8 @@ stages: testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug testArguments: --testCoreClr - ${{ if eq(variables['System.TeamProject'], 'public') }}: - queueName: Build.Ubuntu.1804.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - queueName: Build.Ubuntu.1804.Amd64 + poolName: $(PoolName) + queueName: $(UbuntuQueueName) - template: eng/pipelines/test-unix-job.yml parameters: @@ -279,11 +290,8 @@ stages: testArtifactName: Transport_Artifacts_Unix_Debug configuration: Debug testArguments: --testCoreClr - ${{ if eq(variables['System.TeamProject'], 'public') }}: - helixQueueName: OSX.1015.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - helixQueueName: OSX.1015.Amd64 - helixApiAccessToken: $(HelixApiAccessToken) + helixQueueName: $(HelixMacOsQueueName) + helixApiAccessToken: $(HelixApiAccessToken) - stage: Correctness dependsOn: [] @@ -291,6 +299,7 @@ stages: - template: eng/pipelines/evaluate-changed-files.yml parameters: jobName: Determine_Changes + poolName: $(PoolName) vmImageName: ubuntu-latest paths: - subset: compilers @@ -303,12 +312,8 @@ stages: - job: Correctness_Build_Artifacts dependsOn: Determine_Changes pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal - demands: ImageOverride -equals windows.vs2022preview.amd64 + name: $(PoolName) + demands: ImageOverride -equals $(Vs2022PreviewQueueName) timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -357,12 +362,8 @@ stages: dependsOn: Determine_Changes condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(dependencies.Determine_Changes.outputs['SetPathVars_compilers.containsChange'], 'true')) pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal - demands: ImageOverride -equals windows.vs2022preview.amd64 + name: $(PoolName) + demands: ImageOverride -equals $(Vs2022PreviewQueueName) timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -383,12 +384,8 @@ stages: dependsOn: Determine_Changes condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(dependencies.Determine_Changes.outputs['SetPathVars_compilers.containsChange'], 'true')) pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal - demands: ImageOverride -equals windows.vs2022preview.amd64 + name: $(PoolName) + demands: ImageOverride -equals $(Vs2022PreviewQueueName) timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -433,12 +430,8 @@ stages: dependsOn: Determine_Changes condition: or(ne(variables['Build.Reason'], 'PullRequest'), eq(dependencies.Determine_Changes.outputs['SetPathVars_compilers.containsChange'], 'true')) pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - demands: ImageOverride -equals windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal - demands: ImageOverride -equals windows.vs2022preview.amd64 + name: $(PoolName) + demands: ImageOverride -equals $(Vs2022PreviewQueueName) timeoutInMinutes: 90 variables: - template: eng/pipelines/variables-build.yml @@ -466,12 +459,8 @@ stages: - job: Correctness_Analyzers pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 + name: $(PoolName) + demands: ImageOverride -equals $(UbuntuQueueName) timeoutInMinutes: 35 variables: - template: eng/pipelines/variables-build.yml diff --git a/eng/pipelines/build-unix-job.yml b/eng/pipelines/build-unix-job.yml index 6551a8a5f3b9a..8f9316d88885e 100644 --- a/eng/pipelines/build-unix-job.yml +++ b/eng/pipelines/build-unix-job.yml @@ -9,6 +9,9 @@ parameters: - name: configuration type: string default: 'Debug' +- name: poolName + type: string + default: '' - name: queueName type: string default: '' @@ -20,10 +23,7 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal + name: ${{ parameters.poolName}} demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml index 9776ace7e3184..457ccbe2ba61d 100644 --- a/eng/pipelines/build-windows-job.yml +++ b/eng/pipelines/build-windows-job.yml @@ -9,6 +9,9 @@ parameters: - name: configuration type: string default: 'Debug' +- name: poolName + type: string + default: '' - name: queueName type: string default: '' @@ -26,10 +29,7 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal + name: ${{ parameters.poolName }} demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/checkout-unix-task.yml b/eng/pipelines/checkout-unix-task.yml index 0496d30b3d275..f63c1b433e975 100644 --- a/eng/pipelines/checkout-unix-task.yml +++ b/eng/pipelines/checkout-unix-task.yml @@ -6,21 +6,8 @@ parameters: default: 1 steps: - - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - checkout: none - - - script: | - set -x - git init - git config --local checkout.workers 0 - git config --local fetch.parallel 0 - git remote add origin "$(Build.Repository.Uri)" - git fetch --no-tags --no-auto-maintenance --depth=${{ parameters.depth }} origin "$(Build.SourceVersion)" - git checkout "$(Build.SourceVersion)" - displayName: Shallow Checkout - - ${{ if ne(variables['System.TeamProject'], 'public') }}: - - checkout: self - fetchDepth: ${{ parameters.depth }} - fetchTags: false + - checkout: self + fetchDepth: ${{ parameters.depth }} + fetchTags: false diff --git a/eng/pipelines/checkout-windows-task.yml b/eng/pipelines/checkout-windows-task.yml index 258a0b86d2dd3..d4cc9ca2dbbb3 100644 --- a/eng/pipelines/checkout-windows-task.yml +++ b/eng/pipelines/checkout-windows-task.yml @@ -7,22 +7,8 @@ parameters: # Git path based on https://github.com/microsoft/azure-pipelines-agent/blob/f98a479ab3cc323ff17b8cb75d5ab5f953f342cc/src/Agent.Plugins/GitCliManager.cs#L90 steps: - - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - checkout: none - - - script: | - set PATH=$(Agent.HomeDirectory)\externals\git\cmd;%PATH% - @echo on - git init - git config --local checkout.workers 0 - git config --local fetch.parallel 0 - git remote add origin "$(Build.Repository.Uri)" - git fetch --no-tags --no-auto-maintenance --depth=${{ parameters.depth }} origin "$(Build.SourceVersion)" - git checkout "$(Build.SourceVersion)" - displayName: Shallow Checkout - - ${{ if ne(variables['System.TeamProject'], 'public') }}: - - checkout: self - fetchDepth: ${{ parameters.depth }} - fetchTags: false + - checkout: self + fetchDepth: ${{ parameters.depth }} + fetchTags: false diff --git a/eng/pipelines/evaluate-changed-files.yml b/eng/pipelines/evaluate-changed-files.yml index df79c274cef53..8d2aab8e685d1 100644 --- a/eng/pipelines/evaluate-changed-files.yml +++ b/eng/pipelines/evaluate-changed-files.yml @@ -3,6 +3,9 @@ parameters: - name: jobName type: string default: '' +- name: poolName + type: string + default: '' - name: queueName type: string default: '' @@ -17,10 +20,7 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal + name: ${{ parameters.poolName }} demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/test-unix-job-single-machine.yml b/eng/pipelines/test-unix-job-single-machine.yml index 3958c29569c49..70d944a7ceacd 100644 --- a/eng/pipelines/test-unix-job-single-machine.yml +++ b/eng/pipelines/test-unix-job-single-machine.yml @@ -15,6 +15,9 @@ parameters: - name: testArguments type: string default: '' +- name: poolName + type: string + default: '' - name: queueName type: string default: '' @@ -26,10 +29,7 @@ jobs: - job: ${{ parameters.jobName }} pool: ${{ if ne(parameters.queueName, '') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal + name: ${{ parameters.poolName }} demands: ImageOverride -equals ${{ parameters.queueName }} ${{ if ne(parameters.vmImageName, '') }}: diff --git a/eng/pipelines/test-windows-job-single-machine.yml b/eng/pipelines/test-windows-job-single-machine.yml index b11009a53acf8..2faeae7c19638 100644 --- a/eng/pipelines/test-windows-job-single-machine.yml +++ b/eng/pipelines/test-windows-job-single-machine.yml @@ -15,6 +15,9 @@ parameters: - name: testArguments type: string default: '' +- name: poolName + type: string + default: '' - name: queueName type: string default: 'windows.vs2022.amd64.open' @@ -22,10 +25,7 @@ parameters: jobs: - job: ${{ parameters.jobName }} pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Internal + name: ${{ parameters.poolName }} demands: ImageOverride -equals ${{ parameters.queueName }} timeoutInMinutes: 120 variables: From 01282d16432845681fc234d2a60929988e5d59d1 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Mar 2023 14:11:54 -0800 Subject: [PATCH 044/261] Review feedback --- azure-pipelines.yml | 18 +++++++++--------- eng/pipelines/checkout-windows-task.yml | 1 - 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d4635c54aafa1..d1b6faac53422 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -39,49 +39,49 @@ variables: - name: PoolName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: NetCore-Public - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: NetCore1ESPool-Internal - name: Vs2022PreviewQueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: - value: windows.vs2022preview.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + value: windows.vs2022preview.amd64.open + ${{ else }}: value: windows.vs2022preview.amd64 - name: Vs2022QueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: windows.vs2022.amd64.open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: windows.vs2022.amd64 - name: UbuntuQueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: Build.Ubuntu.1804.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: Build.Ubuntu.1804.Amd64 - name: HelixWindowsQueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: Windows.10.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: Windows.10.Amd64 - name: HelixWindowsSpanishQueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: Windows.10.Amd64.Server2022.ES.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: Windows.10.Amd64.Server2022.ES - name: HelixUbuntuQueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: Ubuntu.1804.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: Ubuntu.1804.Amd64 - name: HelixMacOsQueueName ${{ if eq(variables['System.TeamProject'], 'public') }}: value: OSX.1015.Amd64.Open - ${{ if ne(variables['System.TeamProject'], 'public') }}: + ${{ else }}: value: OSX.1015.Amd64 stages: diff --git a/eng/pipelines/checkout-windows-task.yml b/eng/pipelines/checkout-windows-task.yml index d4cc9ca2dbbb3..f66c019d37942 100644 --- a/eng/pipelines/checkout-windows-task.yml +++ b/eng/pipelines/checkout-windows-task.yml @@ -5,7 +5,6 @@ parameters: type: number default: 1 -# Git path based on https://github.com/microsoft/azure-pipelines-agent/blob/f98a479ab3cc323ff17b8cb75d5ab5f953f342cc/src/Agent.Plugins/GitCliManager.cs#L90 steps: - checkout: self fetchDepth: ${{ parameters.depth }} From 36149eae0723029a25d305a4117a9e3f7b09bce8 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 28 Feb 2023 17:06:04 -0800 Subject: [PATCH 045/261] Get the basic build with the new project working --- Roslyn.sln | 14 + eng/Versions.props | 59 ++-- eng/targets/Settings.props | 1 - ...ft.CodeAnalysis.Collections.Package.csproj | 3 + src/Features/LanguageServer/.editorconfig | 327 ------------------ .../LanguageServer/Directory.Build.props | 4 - .../LanguageServer/Directory.Packages.props | 27 -- .../.editorconfig | 6 - ...deAnalysis.LanguageServer.UnitTests.csproj | 17 +- .../Microsoft.CodeAnalysis.LanguageServer.sln | 39 --- .../.editorconfig | 10 + .../IBrokeredServiceBridgeManifest.cs | 1 + ...crosoft.CodeAnalysis.LanguageServer.csproj | 29 +- src/Features/LanguageServer/NuGet.config | 15 - ...odeAnalysis.LanguageServer.Protocol.csproj | 3 +- src/Features/LanguageServer/global.json | 5 - src/Features/LanguageServer/snk/keypair.snk | Bin 596 -> 0 bytes .../BuildActionTelemetryTable.csproj | 1 + .../BuildValidator/BuildValidator.csproj | 1 + src/Tools/BuildValidator/DemoLogger.cs | 4 +- src/Tools/BuildValidator/Program.cs | 8 +- ...oft.CodeAnalysis.Workspaces.MSBuild.csproj | 2 +- .../Microsoft.CodeAnalysis.Workspaces.csproj | 2 +- .../MEF/ExportProviderCache.cs | 2 +- ...soft.CodeAnalysis.Remote.Workspaces.csproj | 4 +- .../ServiceHub/Host/RemoteWorkspaceManager.cs | 2 +- 26 files changed, 88 insertions(+), 498 deletions(-) delete mode 100644 src/Features/LanguageServer/.editorconfig delete mode 100644 src/Features/LanguageServer/Directory.Packages.props delete mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig delete mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/.editorconfig delete mode 100644 src/Features/LanguageServer/NuGet.config delete mode 100644 src/Features/LanguageServer/global.json delete mode 100644 src/Features/LanguageServer/snk/keypair.snk diff --git a/Roslyn.sln b/Roslyn.sln index 2c43dbf3f3265..ec49ba2fd275a 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -525,6 +525,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Exte EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests", "src\Tools\ExternalAccess\RazorCompilerTest\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests.csproj", "{828FD0DB-9927-42AC-B6C2-D1514965D6C3}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj", "{2A3C94F7-5B5E-4CDC-B645-672815E61DEB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CodeAnalysis.LanguageServer.UnitTests", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer.UnitTests\Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj", "{9A90AA02-4275-40ED-B1F1-731AF17E675C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1283,6 +1287,14 @@ Global {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Release|Any CPU.Build.0 = Release|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.Build.0 = Release|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1522,6 +1534,8 @@ Global {8BC50AFF-1EBF-4E9A-AEBB-04F387AA800F} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} {E5E0BF73-95F7-4BC3-8443-2336C4FF4297} = {8977A560-45C2-4EC2-A849-97335B382C74} {828FD0DB-9927-42AC-B6C2-D1514965D6C3} = {8977A560-45C2-4EC2-A849-97335B382C74} + {2A3C94F7-5B5E-4CDC-B645-672815E61DEB} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} + {9A90AA02-4275-40ED-B1F1-731AF17E675C} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29} diff --git a/eng/Versions.props b/eng/Versions.props index 73f9279a090df..0c912030ad455 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,7 +15,7 @@ Keep the setting conditional. The toolset sets the assembly version to 42.42.42.42 if not set explicitly. --> $(MajorVersion).$(MinorVersion).0.0 - 4.4.0-2.final + 4.5.0 @@ -33,7 +33,7 @@ 6.0.0-rtm.21518.12 17.3.3101 17.5.20-preview - 17.5.0-preview-2-33117-317 + 17.6.35295-preview.2 16.5.0 4.1.0 7.0.0-alpha.1.22060.1 - 4.1.2076-alpha - 17.5.10-alpha + 17.6.24-alpha 17.4.0-preview-20220707-01 6.0.0 6.0.0 - 6.0.0 + 7.0.0 4.5.0 4.5.4 @@ -291,24 +294,14 @@ create a test insertion in Visual Studio to validate. --> 13.0.1 - 2.14.20 + 2.15.4-alpha - 6.0.0 - 6.0.1 - 6.0.0 - - - - $(RestoreSources); - https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json; - - 16.6.15 - - - 16.6.9 + 7.0.0 + 7.0.0 + 7.0.0 true diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index 948df0e3d49b5..0362d4e964ae3 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -99,7 +99,6 @@ $(VisualStudioKey) 0024000004800000940000000602000000240000525341310004000001000100917302efc152e6464679d4625bd9989e12d4662a9eaadf284d04992881c0e7b16e756e63ef200a02c4054d4d31e21b9aa0b0b873bcefca8cd42ec583a3db509665c9b22318ceceec581663fc07e2422bb2135539ba8a517c209ac175fff07c5af10cef636e04cae91d28f51fcde5d14c1a9bfed06e096cf977fd0d60002a3ea6 0024000004800000940000000602000000240000525341310004000001000100e1e4cc8a3ceffcaef02f890a17745185d807f26eae1d31b1b69b84f97a1f57812a999f0f8a624147378c09db1ca669e7f3717ef3710f8ded8067c3b83f24506fae54f18f4e18e1d0df0f21862b58d35aec0917873e92ce8d61ec6b72ba2ebfc418b9ae7da8aa41e0602d5ccc1cf63af0b6cebf3f14f7ca3553233dab3a5eaeab - 002400000480000094000000060200000024000052534131000400000100010009f3c8fcb7cb2592cc6e6d3646d4d9a2bda9e7a243d357bc17a5a06f50ed0dae74a343cd9538fe45bbc90a3f7cbecb23558205e3b246b69f7f7730e520460d560da1c68cda9e2256e3b801629e2dc1fd588b1681aaf4f2c98abcfc50086ecbcd55f76f7dbaf018e708527d8ae3a2714b3ec9b62bd9aaf56cf55b3ffc9eee31aa + true + true true diff --git a/src/Features/LanguageServer/.editorconfig b/src/Features/LanguageServer/.editorconfig deleted file mode 100644 index c061b32160bdf..0000000000000 --- a/src/Features/LanguageServer/.editorconfig +++ /dev/null @@ -1,327 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = false - -# Don't use tabs for indentation. -[*] -indent_style = space -# (Please don't specify an indent_size here; that has too many unintended consequences.) - -# Code files -[*.{cs,csx,vb,vbx}] -indent_size = 4 -insert_final_newline = true -charset = utf-8-bom - -# XML project files -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] -indent_size = 4 - -# XML config files -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] -indent_size = 2 - -# JSON files -[*.json] -indent_size = 2 - -# Powershell files -[*.ps1] -indent_size = 2 - -# Shell script files -[*.sh] -end_of_line = lf -indent_size = 2 - -# Dotnet code style settings: -[*.{cs,vb}] - -# IDE0055: Fix formatting -dotnet_diagnostic.IDE0055.severity = warning - -# Sort using and Import directives with System.* appearing first -dotnet_sort_system_directives_first = true -dotnet_separate_import_directive_groups = false -# Avoid "this." and "Me." if not necessary -dotnet_style_qualification_for_field = false:refactoring -dotnet_style_qualification_for_property = false:refactoring -dotnet_style_qualification_for_method = false:refactoring -dotnet_style_qualification_for_event = false:refactoring - -# Use language keywords instead of framework type names for type references -dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion -dotnet_style_predefined_type_for_member_access = true:suggestion - -# Suggest more modern language features when available -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion - -# Whitespace options -dotnet_style_allow_multiple_blank_lines_experimental = false - -# Non-private static fields are PascalCase -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style - -dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field -dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected -dotnet_naming_symbols.non_private_static_fields.required_modifiers = static - -dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case - -# Non-private readonly fields are PascalCase -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style - -dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field -dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected -dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly - -dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case - -# Constants are PascalCase -dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants -dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style - -dotnet_naming_symbols.constants.applicable_kinds = field, local -dotnet_naming_symbols.constants.required_modifiers = const - -dotnet_naming_style.constant_style.capitalization = pascal_case - -# Static fields are camelCase and start with s_ -dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion -dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields -dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style - -dotnet_naming_symbols.static_fields.applicable_kinds = field -dotnet_naming_symbols.static_fields.required_modifiers = static - -dotnet_naming_style.static_field_style.capitalization = camel_case -dotnet_naming_style.static_field_style.required_prefix = s_ - -# Instance fields are camelCase and start with _ -dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion -dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields -dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style - -dotnet_naming_symbols.instance_fields.applicable_kinds = field - -dotnet_naming_style.instance_field_style.capitalization = camel_case -dotnet_naming_style.instance_field_style.required_prefix = _ - -# Locals and parameters are camelCase -dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion -dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters -dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style - -dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local - -dotnet_naming_style.camel_case_style.capitalization = camel_case - -# Local functions are PascalCase -dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions -dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style - -dotnet_naming_symbols.local_functions.applicable_kinds = local_function - -dotnet_naming_style.local_function_style.capitalization = pascal_case - -# By default, name items with PascalCase -dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members -dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style - -dotnet_naming_symbols.all_members.applicable_kinds = * - -dotnet_naming_style.pascal_case_style.capitalization = pascal_case - -# error RS2008: Enable analyzer release tracking for the analyzer project containing rule '{0}' -dotnet_diagnostic.RS2008.severity = none - -# IDE0073: File header -dotnet_diagnostic.IDE0073.severity = warning -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.\nSee the LICENSE file in the project root for more information. - -# IDE0035: Remove unreachable code -dotnet_diagnostic.IDE0035.severity = warning - -# IDE0036: Order modifiers -dotnet_diagnostic.IDE0036.severity = warning - -# IDE0043: Format string contains invalid placeholder -dotnet_diagnostic.IDE0043.severity = warning - -# IDE0044: Make field readonly -dotnet_diagnostic.IDE0044.severity = warning - -# CONSIDER: Are IDE0051 and IDE0052 too noisy to be warnings for IDE editing scenarios? Should they be made build-only warnings? -# IDE0051: Remove unused private member -dotnet_diagnostic.IDE0051.severity = warning - -# IDE0170: Prefer extended property pattern -dotnet_diagnostic.IDE0170.severity = warning - -# RS0016: Only enable if API files are present -dotnet_public_api_analyzer.require_api_files = true -dotnet_style_operator_placement_when_wrapping = beginning_of_line -tab_width = 4 -end_of_line = crlf -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning -dotnet_style_prefer_auto_properties = true:warning -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:warning - -# CA1802: Use literals where appropriate -dotnet_diagnostic.CA1802.severity = warning - -# CA2007: Do not directly await a Task -dotnet_diagnostic.CA2007.severity = none - -# CA2016: Forward the CancellationToken parameter to methods that take one -dotnet_diagnostic.CA2016.severity = warning - -# CA1848: Use LoggerMessage delegates when calling ILogger methods -dotnet_diagnostic.CA1848.severity = none - -# CA2254: Logging message template should not vary between calls -dotnet_diagnostic.CA2254.severity = none - -# CSharp code style settings: -[*.cs] -# Newline settings -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 = flush_left - -# Whitespace options -csharp_style_allow_embedded_statements_on_same_line_experimental = false -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false - -# Prefer "var" everywhere -csharp_style_var_for_built_in_types = true:suggestion -csharp_style_var_when_type_is_apparent = true:suggestion -csharp_style_var_elsewhere = true:suggestion - -# Prefer method-like constructs to have a block body -csharp_style_expression_bodied_methods = false:none -csharp_style_expression_bodied_constructors = false:none -csharp_style_expression_bodied_operators = false:none - -# Prefer property-like constructs to have an expression-body -csharp_style_expression_bodied_properties = true:none -csharp_style_expression_bodied_indexers = true:none -csharp_style_expression_bodied_accessors = true:none - -# Suggest more modern language features when available -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 -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion -csharp_style_prefer_extended_property_pattern = true:suggestion - -# 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 - -# Blocks are allowed -csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = true -csharp_using_directive_placement = outside_namespace:suggestion -csharp_prefer_simple_using_statement = false:suggestion -csharp_style_namespace_declarations = file_scoped:silent -csharp_style_prefer_method_group_conversion = true:silent -csharp_style_prefer_top_level_statements = true:silent -csharp_style_expression_bodied_lambdas = true:warning -csharp_style_expression_bodied_local_functions = false:warning - -[*.{cs,vb}] - -# IDE0011: Add braces -csharp_prefer_braces = when_multiline:warning -# NOTE: We need the below severity entry for Add Braces due to https://github.com/dotnet/roslyn/issues/44201 -dotnet_diagnostic.IDE0011.severity = warning - -# IDE0040: Add accessibility modifiers -dotnet_diagnostic.IDE0040.severity = warning - -# IDE0052: Remove unread private member -dotnet_diagnostic.IDE0052.severity = warning - -# IDE0059: Unnecessary assignment to a value -dotnet_diagnostic.IDE0059.severity = warning - -# IDE0060: Remove unused parameter -dotnet_diagnostic.IDE0060.severity = warning - -# CA1012: Abstract types should not have public constructors -dotnet_diagnostic.CA1012.severity = warning - -# CA1822: Make member static -dotnet_diagnostic.CA1822.severity = warning - -# Prefer "var" everywhere -dotnet_diagnostic.IDE0007.severity = warning -csharp_style_var_for_built_in_types = true:warning -csharp_style_var_when_type_is_apparent = true:warning -csharp_style_var_elsewhere = true:warning - -# dotnet_style_allow_multiple_blank_lines_experimental -dotnet_diagnostic.IDE2000.severity = warning - -# csharp_style_allow_embedded_statements_on_same_line_experimental -dotnet_diagnostic.IDE2001.severity = warning - -# csharp_style_allow_blank_lines_between_consecutive_braces_experimental -dotnet_diagnostic.IDE2002.severity = warning - -# dotnet_style_allow_statement_immediately_after_block_experimental -dotnet_diagnostic.IDE2003.severity = warning - -# csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental -dotnet_diagnostic.IDE2004.severity = warning - -# VSTHRD003: Avoid awaiting foreign Tasks -dotnet_diagnostic.VSTHRD003.severity = none diff --git a/src/Features/LanguageServer/Directory.Build.props b/src/Features/LanguageServer/Directory.Build.props index dbe752bfd856f..6eef643958f56 100644 --- a/src/Features/LanguageServer/Directory.Build.props +++ b/src/Features/LanguageServer/Directory.Build.props @@ -2,9 +2,5 @@ true - true - latest-All - false - true diff --git a/src/Features/LanguageServer/Directory.Packages.props b/src/Features/LanguageServer/Directory.Packages.props deleted file mode 100644 index fc7ad4650ed29..0000000000000 --- a/src/Features/LanguageServer/Directory.Packages.props +++ /dev/null @@ -1,27 +0,0 @@ - - - - 17.4.0 - 1.5.5 - - 4.6.0-2.23125.2 - $(MicrosoftCodeAnalysisVersion) - $(MicrosoftCodeAnalysisVersion) - $(MicrosoftCodeAnalysisVersion) - $(MicrosoftCodeAnalysisVersion) - $(MicrosoftCodeAnalysisVersion) - - 6.0.0 - 6.0.2 - $(MicrosoftExtensionsLoggingVersion) - - 4.2.49-beta - $(ServiceBrokerVersion) - - 17.2.41 - 17.5.20-preview - 2.9.112 - 2.15.3-alpha - 2.0.0-beta4.22272.1 - - diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig deleted file mode 100644 index 51be17d793683..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/.editorconfig +++ /dev/null @@ -1,6 +0,0 @@ -# This file has specific settings for unit tests - -[*] - -# VSTHRD200: Use "Async" suffix in names of methods that return an awaitable type -dotnet_diagnostic.VSTHRD200.severity = none diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj index da53ec41ae5af..7b88cf4436b03 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj @@ -4,25 +4,14 @@ net7.0 enable enable + UnitTest false - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - + + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln deleted file mode 100644 index 0ca8a563acdc1..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.sln +++ /dev/null @@ -1,39 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer", "Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj", "{2A3C94F7-5B5E-4CDC-B645-672815E61DEB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6BB63E09-D5FD-4EF7-8041-1150449A6058}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - Directory.Build.props = Directory.Build.props - Directory.Packages.props = Directory.Packages.props - NuGet.config = NuGet.config - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CodeAnalysis.LanguageServer.UnitTests", "Microsoft.CodeAnalysis.LanguageServer.UnitTests\Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj", "{9A90AA02-4275-40ED-B1F1-731AF17E675C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.Build.0 = Release|Any CPU - {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9A90AA02-4275-40ED-B1F1-731AF17E675C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {AF07446F-2FE6-4DFD-A110-ABFB60F5FB83} - EndGlobalSection -EndGlobal diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/.editorconfig b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/.editorconfig new file mode 100644 index 0000000000000..e4c1e2f7a4fc5 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/.editorconfig @@ -0,0 +1,10 @@ +[*.cs] + +# CA2007: Consider calling ConfigureAwait on the awaited task +dotnet_diagnostic.CA2007.severity = none + +# CA2007: Do not directly await a Task +dotnet_diagnostic.CA2007.severity = none + +# VSTHRD003: Avoid awaiting foreign Tasks +dotnet_diagnostic.VSTHRD003.severity = none diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs index 750502a70b6f2..8b4df206e01d9 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/IBrokeredServiceBridgeManifest.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Utilities.ServiceBroker; namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.BrokeredServiceBridgeManifest; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index c3883aac60ea9..959b62cdf4f08 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -4,25 +4,31 @@ net7.0 enable enable - ../../artifacts - $(ArtifactsPath)/bin False - $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) - $(ArtifactsPath)/publish/$(Configuration)/$(TargetFramework)/neutral + $(ArtifactsDir)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) + $(ArtifactsDir)/publish/$(Configuration)/$(TargetFramework)/neutral 7.0.0-preview.7.22362.8 LatestMajor + + + + + + + + + + - + + + - - - - @@ -31,13 +37,10 @@ - - - - + diff --git a/src/Features/LanguageServer/NuGet.config b/src/Features/LanguageServer/NuGet.config deleted file mode 100644 index 7ee7ecade6820..0000000000000 --- a/src/Features/LanguageServer/NuGet.config +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index 8284bc1da1163..63f6cf2df5ad0 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -40,7 +40,7 @@ - + @@ -68,7 +68,6 @@ - + diff --git a/src/Tools/BuildValidator/BuildValidator.csproj b/src/Tools/BuildValidator/BuildValidator.csproj index 1a6876b1b3de1..f2e4354388caf 100644 --- a/src/Tools/BuildValidator/BuildValidator.csproj +++ b/src/Tools/BuildValidator/BuildValidator.csproj @@ -26,6 +26,7 @@ + diff --git a/src/Tools/BuildValidator/DemoLogger.cs b/src/Tools/BuildValidator/DemoLogger.cs index 052001ec4ef59..ac282792ccacd 100644 --- a/src/Tools/BuildValidator/DemoLogger.cs +++ b/src/Tools/BuildValidator/DemoLogger.cs @@ -39,7 +39,7 @@ public IDisposable BeginScope(TState state) public bool IsEnabled(LogLevel logLevel) => true; - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) => LogCore(formatter(state, exception)); private void LogCore(string? message) @@ -70,7 +70,7 @@ public void Dispose() public bool IsEnabled(LogLevel logLevel) => false; - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { } } diff --git a/src/Tools/BuildValidator/Program.cs b/src/Tools/BuildValidator/Program.cs index 6effc03da8c94..8a913462df5d7 100644 --- a/src/Tools/BuildValidator/Program.cs +++ b/src/Tools/BuildValidator/Program.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.CommandLine; -using System.CommandLine.Invocation; +using System.CommandLine.NamingConventionBinder; using System.IO; using System.Linq; using System.Reflection.PortableExecutable; @@ -35,16 +35,16 @@ static int Main(string[] args) { new Option( "--assembliesPath", BuildValidatorResources.Path_to_assemblies_to_rebuild_can_be_specified_one_or_more_times - ) { IsRequired = true, Argument = { Arity = ArgumentArity.OneOrMore } }, + ) { IsRequired = true, Arity = ArgumentArity.OneOrMore }, new Option( "--exclude", BuildValidatorResources.Assemblies_to_be_excluded_substring_match - ) { Argument = { Arity = ArgumentArity.ZeroOrMore } }, + ) { Arity = ArgumentArity.ZeroOrMore }, new Option( "--sourcePath", BuildValidatorResources.Path_to_sources_to_use_in_rebuild ) { IsRequired = true }, new Option( "--referencesPath", BuildValidatorResources.Path_to_referenced_assemblies_can_be_specified_zero_or_more_times - ) { Argument = { Arity = ArgumentArity.ZeroOrMore } }, + ) { Arity = ArgumentArity.ZeroOrMore }, new Option( "--verbose", BuildValidatorResources.Output_verbose_log_information ), diff --git a/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj b/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj index 0dc0700b7000d..bb28be39247ba 100644 --- a/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj +++ b/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 80b40f2ef9610..8f6b196fca048 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -60,7 +60,7 @@ - + diff --git a/src/Workspaces/CoreTestUtilities/MEF/ExportProviderCache.cs b/src/Workspaces/CoreTestUtilities/MEF/ExportProviderCache.cs index 7b59fcbab923d..342d8f72bd313 100644 --- a/src/Workspaces/CoreTestUtilities/MEF/ExportProviderCache.cs +++ b/src/Workspaces/CoreTestUtilities/MEF/ExportProviderCache.cs @@ -259,7 +259,7 @@ private sealed class SimpleAssemblyLoader : IAssemblyLoader public Assembly LoadAssembly(AssemblyName assemblyName) => Assembly.Load(assemblyName); - public Assembly LoadAssembly(string assemblyFullName, string codeBasePath) + public Assembly LoadAssembly(string assemblyFullName, string? codeBasePath) { var assemblyName = new AssemblyName(assemblyFullName); if (!string.IsNullOrEmpty(codeBasePath)) diff --git a/src/Workspaces/Remote/Core/Microsoft.CodeAnalysis.Remote.Workspaces.csproj b/src/Workspaces/Remote/Core/Microsoft.CodeAnalysis.Remote.Workspaces.csproj index a792c6aee9825..fce054f51f6eb 100644 --- a/src/Workspaces/Remote/Core/Microsoft.CodeAnalysis.Remote.Workspaces.csproj +++ b/src/Workspaces/Remote/Core/Microsoft.CodeAnalysis.Remote.Workspaces.csproj @@ -45,8 +45,8 @@ - - + + diff --git a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs index 952030ff96008..b149b702620d6 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs @@ -147,7 +147,7 @@ private sealed class SimpleAssemblyLoader : IAssemblyLoader public Assembly LoadAssembly(AssemblyName assemblyName) => Assembly.Load(assemblyName); - public Assembly LoadAssembly(string assemblyFullName, string codeBasePath) + public Assembly LoadAssembly(string assemblyFullName, string? codeBasePath) { var assemblyName = new AssemblyName(assemblyFullName); if (!string.IsNullOrEmpty(codeBasePath)) From 5061675bc7e5cd837fe2e197c143a8f075616f7f Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Mar 2023 17:33:51 -0800 Subject: [PATCH 046/261] Fix analyzer warnings --- .../BrokeredServiceBridgeProvider.cs | 2 ++ .../BrokeredServiceTraceLogger.cs | 2 ++ .../BrokeredServices/MefServiceBroker.cs | 15 +++++++++++---- .../BrokeredServices/ServiceBrokerMefExport.cs | 9 +++++++++ .../BrokeredServiceBridgeManifestService.cs | 4 ++++ .../Services/HelloWorld/HelloWorldService.cs | 10 ++++++++++ .../HelloWorld/RemoteHelloWorldProvider.cs | 5 +++++ .../HostServicesProvider.cs | 1 + .../HostWorkspace/FileChangeWatcher.cs | 7 +++++++ .../HostWorkspace/LanguageServerProjectSystem.cs | 2 ++ .../HostWorkspace/MetadataService.cs | 9 ++++++++- .../WorkspaceProjectFactoryService.cs | 5 ++++- .../WorkspaceRegistrationService.cs | 2 ++ .../Logging/ServerLoggerFactory.cs | 7 +++++++ 14 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs index 2a8393b616b77..e140b28f60d29 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceBridgeProvider.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Composition; using System.Diagnostics; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; using Microsoft.Extensions.Logging; using Microsoft.ServiceHub.Framework; @@ -23,6 +24,7 @@ internal class BrokeredServiceBridgeProvider private readonly TraceSource _brokeredServiceTraceSource; [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public BrokeredServiceBridgeProvider(ILoggerFactory loggerFactory, BrokeredServiceTraceListener brokeredServiceTraceListener) { _logger = loggerFactory.CreateLogger(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs index 4d38a6eb8bb82..a4369dde1428e 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs @@ -4,6 +4,7 @@ using System.Composition; using System.Diagnostics; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; @@ -16,6 +17,7 @@ internal class BrokeredServiceTraceListener : TraceListener public TraceSource Source { get; } [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public BrokeredServiceTraceListener(ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger(nameof(BrokeredServiceTraceListener)); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs index 43a1361fbf9b4..2e8b559d8c0e5 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/MefServiceBroker.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Shell.ServiceBroker; using Microsoft.VisualStudio.Utilities.ServiceBroker; using Roslyn.Utilities; @@ -12,15 +13,21 @@ namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; [Export, Shared] internal class MefServiceBroker : ServiceBrokerOfExportedServices { + private readonly BrokeredServiceContainer _container; + private Task? containerTask; - [Import("PrivateBrokeredServiceContainer")] - internal BrokeredServiceContainer BrokeredServiceContainer { get; private set; } = null!; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public MefServiceBroker([Import("PrivateBrokeredServiceContainer")] BrokeredServiceContainer brokeredServiceContainer) + { + _container = brokeredServiceContainer; + } protected override Task GetBrokeredServiceContainerAsync(CancellationToken cancellationToken) { - Contract.ThrowIfNull(BrokeredServiceContainer, $"{nameof(this.BrokeredServiceContainer)} must be set first."); - this.containerTask ??= Task.FromResult((GlobalBrokeredServiceContainer)this.BrokeredServiceContainer); + Contract.ThrowIfNull(_container, $"{nameof(_container)} must be set first."); + this.containerTask ??= Task.FromResult((GlobalBrokeredServiceContainer)_container); return this.containerTask; } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs index e350400c67047..2156453fee10e 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerMefExport.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Shell.ServiceBroker; @@ -18,12 +19,20 @@ namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; /// based on their own service queries. /// MEF will dispose of each instance as its lifetime comes to an end. /// +#pragma warning disable RS0030 // This is intentionally using System.ComponentModel.Composition for compatibility with MEF service broker. [Export] internal class ServiceBrokerMefExport { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public ServiceBrokerMefExport() + { + } + [Export(typeof(SVsFullAccessServiceBroker))] public IServiceBroker ServiceBroker => this.Container?.GetFullAccessServiceBroker() ?? throw new InvalidOperationException($"Set {nameof(this.Container)} first."); [Export("PrivateBrokeredServiceContainer")] internal BrokeredServiceContainer? Container { get; set; } } +#pragma warning restore RS0030 // Do not used banned APIs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs index 6e642bbc4b479..d4c28b9aa273e 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/BrokeredServiceBridgeManifest/BrokeredServiceBridgeManifestService.cs @@ -4,11 +4,13 @@ using System.Collections.Immutable; using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Shell.ServiceBroker; namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.BrokeredServiceBridgeManifest; +#pragma warning disable RS0030 // This is intentionally using System.ComponentModel.Composition for compatibility with MEF service broker. [ExportBrokeredService(MonikerName, MonikerVersion, Audience = ServiceAudience.Local)] internal class BrokeredServiceBridgeManifest : IBrokeredServiceBridgeManifest, IExportedBrokeredService { @@ -23,6 +25,7 @@ internal class BrokeredServiceBridgeManifest : IBrokeredServiceBridgeManifest, I private readonly BrokeredServiceContainer _container; [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public BrokeredServiceBridgeManifest([Import("PrivateBrokeredServiceContainer")] BrokeredServiceContainer container) { _container = container; @@ -44,3 +47,4 @@ public Task InitializeAsync(CancellationToken cancellationToken) return Task.CompletedTask; } } +#pragma warning restore RS0030 // Do not used banned APIs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs index 4a38f54762f61..262e82b6b6a82 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/HelloWorldService.cs @@ -2,17 +2,26 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Shell.ServiceBroker; namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; +#pragma warning disable RS0030 // This is intentionally using System.ComponentModel.Composition for compatibility with MEF service broker. [ExportBrokeredService(MonikerName, MonikerVersion, Audience = ServiceAudience.AllClientsIncludingGuests | ServiceAudience.Local)] internal class HelloWorldService : IHelloWorld, IExportedBrokeredService { internal const string MonikerName = "Microsoft.CodeAnalysis.LanguageServer.IHelloWorld"; internal const string MonikerVersion = "0.1"; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public HelloWorldService() + { + } + public ServiceRpcDescriptor Descriptor => Descriptors.LocalHelloWorldService; public Task InitializeAsync(CancellationToken cancellationToken) @@ -30,3 +39,4 @@ public Task CallMeAsync(ServiceMoniker serviceMoniker, CancellationToken throw new NotImplementedException(); } } +#pragma warning restore RS0030 // Do not used banned APIs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs index 35591f7f1eda4..664657bae6008 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/Services/HelloWorld/RemoteHelloWorldProvider.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.Extensions.Logging; using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Shell.ServiceBroker; @@ -10,6 +11,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; +#pragma warning disable RS0030 // This is intentionally using System.ComponentModel.Composition for compatibility with MEF service broker. [Export] internal class RemoteHelloWorldProvider { @@ -18,6 +20,7 @@ internal class RemoteHelloWorldProvider private readonly ILogger _logger; [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public RemoteHelloWorldProvider([Import(typeof(SVsFullAccessServiceBroker))] IServiceBroker serviceBroker, ILoggerFactory loggerFactory) { _serviceBroker = serviceBroker; @@ -65,3 +68,5 @@ private async Task TryGetHelloWorldAsync(CancellationToken cancellationTok return false; } } + +#pragma warning restore RS0030 // Do not used banned APIs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs index 12578596178d6..203e6685213bd 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostServicesProvider.cs @@ -18,6 +18,7 @@ internal class HostServicesProvider public HostServices HostServices { get; } [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public HostServicesProvider(ExportProvider exportProvider) { HostServices = MefV1HostServices.Create(exportProvider.AsExportProvider()); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs index 0de3ff2197def..c0e065bb13961 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.ProjectSystem; using Roslyn.Utilities; @@ -12,6 +13,12 @@ namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; [Export(typeof(IFileChangeWatcher)), Shared] internal sealed class FileChangeWatcher : IFileChangeWatcher { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public FileChangeWatcher() + { + } + public IFileChangeContext CreateContext(params WatchedDirectory[] watchedDirectories) { return new FileChangeContext(watchedDirectories.ToImmutableArray()); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index c818520a6db28..2a2ee2dccc159 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; using Microsoft.CodeAnalysis.MSBuild; using Microsoft.CodeAnalysis.MSBuild.Build; @@ -36,6 +37,7 @@ internal sealed class LanguageServerProjectSystem private readonly ConcurrentDictionary> _loadedProjects = new(); [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VSCodeAnalyzerLoader analyzerLoader, IFileChangeWatcher fileChangeWatcher, ILoggerFactory loggerFactory, IAsynchronousOperationListenerProvider listenerProvider) { _logger = loggerFactory.CreateLogger(nameof(LanguageServerProjectSystem)); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs index e4261f21e3dab..7d8bcdd7ad732 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/MetadataService.cs @@ -2,14 +2,21 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Composition; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; -[ExportWorkspaceServiceFactory(typeof(IMetadataService), ServiceLayer.Host)] +[ExportWorkspaceServiceFactory(typeof(IMetadataService), ServiceLayer.Host), Shared] internal sealed class MetadataServiceFactory : IWorkspaceServiceFactory { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public MetadataServiceFactory() + { + } + public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) { return new MetadataService(workspaceServices.GetRequiredService()); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs index 93880ab12ef3e..132755243c825 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/WorkspaceProjectFactoryService.cs @@ -4,12 +4,13 @@ using System.Collections.Immutable; using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Remote.ProjectSystem; using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Shell.ServiceBroker; namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; - +#pragma warning disable RS0030 // This is intentionally using System.ComponentModel.Composition for compatibility with MEF service broker. /// /// An implementation of the brokered service that just maps calls to the underlying project system. /// @@ -19,6 +20,7 @@ internal class WorkspaceProjectFactoryService : IWorkspaceProjectFactoryService, private readonly LanguageServerProjectSystem _projectSystem; [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public WorkspaceProjectFactoryService(LanguageServerProjectSystem projectSystem) { _projectSystem = projectSystem; @@ -54,3 +56,4 @@ public Task> GetSupportedBuildSystemPropertiesAsync( return Task.FromResult((IReadOnlyCollection)ImmutableArray.Empty); } } +#pragma warning restore RS0030 // Do not used banned APIs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs index 88919ded2703a..527706959a8ca 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Composition; +using Microsoft.CodeAnalysis.Host.Mef; namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; @@ -14,6 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; internal class WorkspaceRegistrationService : LspWorkspaceRegistrationService { [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public WorkspaceRegistrationService() { diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs index e46f1ea0e61de..84ea12bffbd89 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ServerLoggerFactory.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Composition; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.Extensions.Logging; using Roslyn.Utilities; @@ -15,6 +16,12 @@ internal class ServerLoggerFactory : ILoggerFactory { private ILoggerFactory? _loggerFactory; + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public ServerLoggerFactory() + { + } + public void SetFactory(ILoggerFactory loggerFactory) { Contract.ThrowIfTrue(_loggerFactory is not null); From 29eecfeaaffd2d7c6c9db781a69d33003fd8ccbf Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Mar 2023 17:35:28 -0800 Subject: [PATCH 047/261] Fix build boss warning --- Roslyn.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roslyn.sln b/Roslyn.sln index ec49ba2fd275a..7e3cad4019b2e 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -527,7 +527,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Exte EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj", "{2A3C94F7-5B5E-4CDC-B645-672815E61DEB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CodeAnalysis.LanguageServer.UnitTests", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer.UnitTests\Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj", "{9A90AA02-4275-40ED-B1F1-731AF17E675C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.UnitTests", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer.UnitTests\Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj", "{9A90AA02-4275-40ED-B1F1-731AF17E675C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From ed9f0c78cb92c4682f0887e0321b7f93cde78595 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Mar 2023 18:06:33 -0800 Subject: [PATCH 048/261] Use MEF in WorkspaceProjectFactoryServiceTests to access brokered service --- .../WorkspaceProjectFactoryServiceTests.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs index 778874e72e428..05ab733f018e0 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.CodeAnalysis.Remote.ProjectSystem; using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Shell.ServiceBroker; namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; public class WorkspaceProjectFactoryServiceTests @@ -17,9 +18,12 @@ public async Task CreateProjectAndBatch() exportProvider.GetExportedValue().SetFactory(new LoggerFactory()); var projectSystem = exportProvider.GetExportedValue(); + var workspaceProjectFactoryServiceInstance = (WorkspaceProjectFactoryService)exportProvider + .GetExportedValues() + .Single(service => service.Descriptor == WorkspaceProjectFactoryServiceDescriptor.ServiceDescriptor); await using var brokeredServiceFactory = new BrokeredServiceProxy( - new WorkspaceProjectFactoryService(projectSystem)); + workspaceProjectFactoryServiceInstance); var workspaceProjectFactoryService = await brokeredServiceFactory.GetServiceAsync(); using var workspaceProject = await workspaceProjectFactoryService.CreateAndAddProjectAsync( From 2cb55565c05719ca51f6b4cfbff6d8f23deda868 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 2 Mar 2023 18:16:24 -0800 Subject: [PATCH 049/261] Fix MEF composition failures in analyzer testing library --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 0c912030ad455..379ca0d1af97d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -21,7 +21,7 @@ 3.3.4-beta1.22579.2 8.0.0-preview1.23111.1 - 1.1.2-beta1.22512.1 + 1.1.2-beta1.23115.1 0.1.149-beta 4.3.0-1.final From f58b27a6d7126a031288de047aff6603d18061b9 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Fri, 3 Mar 2023 11:57:24 -0800 Subject: [PATCH 050/261] Fix issue with a watched directory not being present If a watched directory wasn't there, we'd throw. Now we'll just skip watching it, on the assumption that we probably won't later get a request to watch a file under there. Even if we do, we'll correctly handle that case (just less efficiently.) --- .../HostWorkspace/FileChangeWatcher.cs | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs index c0e065bb13961..6ef9a71e3e7fe 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs @@ -36,28 +36,37 @@ private class FileChangeContext : IFileChangeContext public FileChangeContext(ImmutableArray watchedDirectories) { - _watchedDirectories = watchedDirectories; - var builder = ImmutableArray.CreateBuilder(watchedDirectories.Length); + var watchedDirectoriesBuilder = ImmutableArray.CreateBuilder(watchedDirectories.Length); + var watcherBuilder = ImmutableArray.CreateBuilder(watchedDirectories.Length); foreach (var watchedDirectory in watchedDirectories) { - var watcher = new FileSystemWatcher(watchedDirectory.Path); - watcher.IncludeSubdirectories = true; + // If the directory doesn't exist, we can't create a watcher for changes inside of it. In this case, we'll just skip this as a directory + // to watch; any requests for a watch within that directory will still create a one-off watcher for that specific file. That's not likely + // to be an issue in practice: directories that are missing would be things like global reference directories -- if it's not there, we + // probably won't ever see a watch for a file under there later anyways. + if (Directory.Exists(watchedDirectory.Path)) + { + var watcher = new FileSystemWatcher(watchedDirectory.Path); + watcher.IncludeSubdirectories = true; - if (watchedDirectory.ExtensionFilter != null) - watcher.Filter = '*' + watchedDirectory.ExtensionFilter; + if (watchedDirectory.ExtensionFilter != null) + watcher.Filter = '*' + watchedDirectory.ExtensionFilter; - watcher.Changed += RaiseEvent; - watcher.Created += RaiseEvent; - watcher.Deleted += RaiseEvent; - watcher.Renamed += RaiseEvent; + watcher.Changed += RaiseEvent; + watcher.Created += RaiseEvent; + watcher.Deleted += RaiseEvent; + watcher.Renamed += RaiseEvent; - watcher.EnableRaisingEvents = true; + watcher.EnableRaisingEvents = true; - builder.Add(watcher); + watchedDirectoriesBuilder.Add(watchedDirectory); + watcherBuilder.Add(watcher); + } } - _directoryFileSystemWatchers = builder.ToImmutable(); + _watchedDirectories = watchedDirectoriesBuilder.ToImmutable(); + _directoryFileSystemWatchers = watcherBuilder.ToImmutable(); } public event EventHandler? FileChanged; From 0b51e0dc17f61c420624b9345fdc8d41af2cfcd8 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 3 Mar 2023 13:14:31 -0800 Subject: [PATCH 051/261] Use same version of servicehub framework that servicehub client uses --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 379ca0d1af97d..1d1f1ba9cff4e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -130,7 +130,7 @@ 0.1.0 0.1.2-dev 4.1.5125-alpha - 4.2.70-beta + 4.2.53-beta 1.1.1-beta-21566-01 16.170.0 $(MicrosoftTestPlatformVersion) From 1df06b9a9b36468af5b42f5784535673941ff752 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 3 Mar 2023 13:51:44 -0800 Subject: [PATCH 052/261] Fix arguments to use appropriate types for new system.commandline version --- src/Tools/BuildValidator/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Tools/BuildValidator/Program.cs b/src/Tools/BuildValidator/Program.cs index 8a913462df5d7..dace7380a3328 100644 --- a/src/Tools/BuildValidator/Program.cs +++ b/src/Tools/BuildValidator/Program.cs @@ -33,16 +33,16 @@ static int Main(string[] args) System.Diagnostics.Trace.Listeners.Clear(); var rootCommand = new RootCommand { - new Option( + new Option( "--assembliesPath", BuildValidatorResources.Path_to_assemblies_to_rebuild_can_be_specified_one_or_more_times ) { IsRequired = true, Arity = ArgumentArity.OneOrMore }, - new Option( + new Option( "--exclude", BuildValidatorResources.Assemblies_to_be_excluded_substring_match ) { Arity = ArgumentArity.ZeroOrMore }, new Option( "--sourcePath", BuildValidatorResources.Path_to_sources_to_use_in_rebuild ) { IsRequired = true }, - new Option( + new Option( "--referencesPath", BuildValidatorResources.Path_to_referenced_assemblies_can_be_specified_zero_or_more_times ) { Arity = ArgumentArity.ZeroOrMore }, new Option( From 709ce87b579b97a67f4987d8bfddcf00c29b8d38 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Wed, 1 Mar 2023 13:44:00 -0800 Subject: [PATCH 053/261] Replace the direct use of the JsonRpc object with the LSP service This avoids leaking the JsonRpc object directly outside of the host type and instead calls the abstraction the rest of the system uses. --- .../LanguageServer/LanguageServerHost.cs | 5 +++-- .../Logging/LspLogMessageLogger.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index 1fd6288384dde..e442a5d788f25 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -15,6 +15,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer; internal sealed class LanguageServerHost #pragma warning restore CA1001 // The JsonRpc instance is disposed of by the AbstractLanguageServer during shutdown { + // TODO: replace this with a MEF part instead /// /// A static reference to the server instance. /// Used by loggers to determine if they can send log messages via LSP @@ -61,8 +62,8 @@ public async Task WaitForExitAsync() await _roslynLanguageServer.WaitForExitAsync(); } - public Task NotifyAsync(string targetName, object? argument) + public T GetRequiredLspService() where T : ILspService { - return _jsonRpc.NotifyAsync(targetName, argument); + return _roslynLanguageServer.GetLspServices().GetRequiredService(); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs index b3390b7e142e6..9435d7b847dae 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs @@ -49,7 +49,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except if (message != null && logLevel != LogLevel.None) { message = $"[{_categoryName}]{message}"; - var _ = server.NotifyAsync(Methods.WindowLogMessageName, new LogMessageParams() + var _ = server.GetRequiredLspService().SendNotificationAsync(Methods.WindowLogMessageName, new LogMessageParams() { Message = message, MessageType = logLevel switch @@ -62,7 +62,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except LogLevel.Critical => MessageType.Error, _ => throw new InvalidOperationException($"Unexpected logLevel argument {logLevel}"), } - }); + }, CancellationToken.None); } } } From 58f0133ae5dd5065edbe0cc39bafade88f6acb40 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Fri, 3 Mar 2023 17:28:14 -0800 Subject: [PATCH 054/261] Add support for Razor dynamic files This sends requests for Razor dynamic files back through the LSP channel so the LSP client can then route it to the Razor extension. --- .../LanguageServerProjectSystem.cs | 10 +- .../HostWorkspace/LoadedProject.cs | 13 +++ .../RazorDynamicFileInfoProvider.cs | 99 +++++++++++++++++++ .../LanguageServer/LanguageServerHost.cs | 3 +- 4 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index 2a2ee2dccc159..df0a2686253ec 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -38,7 +38,13 @@ internal sealed class LanguageServerProjectSystem [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VSCodeAnalyzerLoader analyzerLoader, IFileChangeWatcher fileChangeWatcher, ILoggerFactory loggerFactory, IAsynchronousOperationListenerProvider listenerProvider) + public LanguageServerProjectSystem( + HostServicesProvider hostServicesProvider, + VSCodeAnalyzerLoader analyzerLoader, + IFileChangeWatcher fileChangeWatcher, + [ImportMany] IEnumerable> dynamicFileInfoProviders, + ILoggerFactory loggerFactory, + IAsynchronousOperationListenerProvider listenerProvider) { _logger = loggerFactory.CreateLogger(nameof(LanguageServerProjectSystem)); Workspace = new LanguageServerWorkspace(hostServicesProvider.HostServices); @@ -57,7 +63,7 @@ public LanguageServerProjectSystem(HostServicesProvider hostServicesProvider, VS CancellationToken.None); // TODO: do we need to introduce a shutdown cancellation token for this? ProjectSystemHostInfo = new ProjectSystemHostInfo( - DynamicFileInfoProviders: ImmutableArray>.Empty, + DynamicFileInfoProviders: dynamicFileInfoProviders.ToImmutableArray(), new ProjectSystemDiagnosticSource(), new HostDiagnosticAnalyzerProvider()); _fileChangeWatcher = fileChangeWatcher; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs index 2b3ed31a4bb33..80a9f1e4f0744 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs @@ -119,6 +119,13 @@ public async ValueTask UpdateWithNewProjectInfoAsync(ProjectFileInfo newProjectI document => _projectSystemProject.AddAnalyzerConfigFile(document.FilePath), document => _projectSystemProject.RemoveAnalyzerConfigFile(document.FilePath)); + UpdateProjectSystemProjectCollection( + newProjectInfo.AdditionalDocuments.Where(TreatAsIsDynamicFile).Distinct(DocumentFileInfoComparer.Instance), // TODO: figure out why we have duplicates + _mostRecentFileInfo?.AdditionalDocuments.Where(TreatAsIsDynamicFile).Distinct(DocumentFileInfoComparer.Instance), + DocumentFileInfoComparer.Instance, + document => _projectSystemProject.AddDynamicSourceFile(document.FilePath, folders: ImmutableArray.Empty), + document => _projectSystemProject.RemoveAdditionalFile(document.FilePath)); + _mostRecentFileInfo = newProjectInfo; return; @@ -147,6 +154,12 @@ static void UpdateProjectSystemProjectCollection(IEnumerable loadedCollect } } + private static bool TreatAsIsDynamicFile(DocumentFileInfo info) + { + var extension = Path.GetExtension(info.FilePath); + return extension is ".cshtml" or ".razor"; + } + private sealed class DocumentFileInfoComparer : IEqualityComparer { public static IEqualityComparer Instance = new DocumentFileInfoComparer(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs new file mode 100644 index 0000000000000..a06276d7b76ee --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using System.Runtime.Serialization; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +[Export(typeof(IDynamicFileInfoProvider)), Shared] +[ExportMetadata("Extensions", new string[] { "cshtml", "razor", })] +internal class RazorDynamicFileInfoProvider : IDynamicFileInfoProvider +{ + private const string ProvideRazorDynamicFileInfoMethodName = "razor/provideDynamicFileInfo"; + + [DataContract] + private class ProvideDynamicFileParams + { + [DataMember(Name = "razorFiles")] + public required Uri[] RazorFiles { get; set; } + } + + [DataContract] + private class ProvideDynamicFileResponse + { + [DataMember(Name = "generatedFiles")] + public required Uri[] GeneratedFiles { get; set; } + } + + private const string RemoveRazorDynamicFileInfoMethodName = "razor/removeDynamicFileInfo"; + + [DataContract] + private class RemoveDynamicFileParams + { + [DataMember(Name = "razorFiles")] + public required Uri[] RazorFiles { get; set; } + } + +#pragma warning disable CS0067 // We won't fire the Updated event -- we expect Razor to send us textual changes via didChange instead + public event EventHandler? Updated; +#pragma warning restore CS0067 + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public RazorDynamicFileInfoProvider() + { + } + + public async Task GetDynamicFileInfoAsync(ProjectId projectId, string? projectFilePath, string filePath, CancellationToken cancellationToken) + { + var requestParams = new ProvideDynamicFileParams { RazorFiles = new[] { ProtocolConversions.GetUriFromFilePath(filePath) } }; + + Contract.ThrowIfNull(LanguageServerHost.Instance, "We don't have an LSP channel yet to send this request through."); + var clientLanguageServerManager = LanguageServerHost.Instance.GetRequiredLspService(); + + var response = await clientLanguageServerManager.SendRequestAsync( + ProvideRazorDynamicFileInfoMethodName, requestParams, cancellationToken); + + // Since we only sent one file over, we should get either zero or one URI back + var responseUri = response.GeneratedFiles.SingleOrDefault(); + + if (responseUri == null) + { + return null; + } + else + { + return new DynamicFileInfo(responseUri.LocalPath, SourceCodeKind.Regular, EmptyStringTextLoader.Instance, designTimeOnly: true, documentServiceProvider: null); + } + } + + public Task RemoveDynamicFileInfoAsync(ProjectId projectId, string? projectFilePath, string filePath, CancellationToken cancellationToken) + { + var notificationParams = new RemoveDynamicFileParams { RazorFiles = new[] { ProtocolConversions.GetUriFromFilePath(filePath) } }; + + Contract.ThrowIfNull(LanguageServerHost.Instance, "We don't have an LSP channel yet to send this request through."); + var clientLanguageServerManager = LanguageServerHost.Instance.GetRequiredLspService(); + + return clientLanguageServerManager.SendNotificationAsync( + RemoveRazorDynamicFileInfoMethodName, notificationParams, cancellationToken).AsTask(); + } + + private sealed class EmptyStringTextLoader : TextLoader + { + public static readonly TextLoader Instance = new EmptyStringTextLoader(); + + private EmptyStringTextLoader() { } + + public override Task LoadTextAndVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) + { + return Task.FromResult(TextAndVersion.Create(SourceText.From(""), VersionStamp.Default)); + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs index e442a5d788f25..03803c10aad83 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs @@ -18,8 +18,7 @@ internal sealed class LanguageServerHost // TODO: replace this with a MEF part instead /// /// A static reference to the server instance. - /// Used by loggers to determine if they can send log messages via LSP - /// or if they need to use a fallback mechanism. + /// Used by components to send notifications and requests back to the client. /// internal static LanguageServerHost? Instance { get; private set; } From 4b99331226e98109b7308651f467c2f4304dd7a2 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Mon, 6 Mar 2023 18:08:36 -0800 Subject: [PATCH 055/261] Work around bug in LoggingExtensions This works around https://github.com/dotnet/runtime/issues/67597 --- .../Logging/LspLogMessageLogger.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs index b3390b7e142e6..728172d3a3cda 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/LspLogMessageLogger.cs @@ -46,6 +46,18 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } var message = formatter(state, exception); + + // HACK: work around https://github.com/dotnet/runtime/issues/67597: the formatter function we passed the exception to completely ignores the exception, + // we'll add an exception message back in. If we didn't have a message, we'll just replace it with the exception text. + if (exception != null) + { + var exceptionString = exception.ToString(); + if (message == "[null]") // https://github.com/dotnet/runtime/blob/013ca673f6316dbbe71c7b327d7b8fa41cf8c992/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/FormattedLogValues.cs#L19 + message = exceptionString; + else + message += " " + exceptionString; + } + if (message != null && logLevel != LogLevel.None) { message = $"[{_categoryName}]{message}"; From e186f07a02305b84ab5963293da36317d8f4d1e1 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 6 Mar 2023 17:19:09 -0800 Subject: [PATCH 056/261] Build and publish r2r server executables --- azure-pipelines-official.yml | 11 +++ eng/config/runtimeconfig.template.json | 2 +- ...crosoft.CodeAnalysis.LanguageServer.csproj | 84 +++++++++++++++++-- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 7870a97ddc6ca..b3692a03e499c 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -303,6 +303,17 @@ stages: ArtifactName: 'PackageArtifacts' condition: succeeded() + # Publish our language server executables as an artifact. + - task: NuGetCommand@2 + displayName: Publish Language Server Executables + inputs: + command: push + packagesToPush: '$(Build.SourcesDirectory)\artifacts\LanguageServer\*.nupkg' + allowPackageConflicts: false + nuGetFeedType: external + publishFeedCredentials: 'DevDiv - VS package feed' + condition: succeeded() + # Publish Asset Manifests for Build Asset Registry job - task: PublishBuildArtifacts@1 displayName: Publish Asset Manifests diff --git a/eng/config/runtimeconfig.template.json b/eng/config/runtimeconfig.template.json index 384e2f49e4b29..e46db7a06283c 100644 --- a/eng/config/runtimeconfig.template.json +++ b/eng/config/runtimeconfig.template.json @@ -1,3 +1,3 @@ { - "rollForwardOnNoCandidateFx": 2 + "rollForward": "Major" } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 959b62cdf4f08..bffb24e4602a5 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -5,13 +5,39 @@ enable enable + + true + + PublishAllRids;$(BeforePack) + + NU5100 + + $(ArtifactsDir)/LanguageServer + - False - $(ArtifactsDir)/publish/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) - $(ArtifactsDir)/publish/$(Configuration)/$(TargetFramework)/neutral - + false + $(ArtifactsDir)/LanguageServer/$(Configuration)/$(TargetFramework)/$(RuntimeIdentifier) + $(ArtifactsDir)/LanguageServer/$(Configuration)/$(TargetFramework)/neutral + 7.0.0-preview.7.22362.8 - LatestMajor + + + win-x64;win-x86;win-arm64;linux-x64;linux-arm64;alpine-x64;alpine-arm64;osx-x64;osx-arm64 + + true @@ -26,8 +52,6 @@ - - @@ -56,4 +80,50 @@ + + + + + + + + + + + RuntimeIdentifier=%(RuntimeIdentifierForPublish.Identity) + + + + + + + + + + + + + true + content\LanguageServer + false + None + + + From bed4660cccf27a9a0a992bcb7351637d3b7a815d Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 8 Mar 2023 18:56:39 -0800 Subject: [PATCH 057/261] Automatically run builds on features/lsp_tools_host --- azure-pipelines-official.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index b3692a03e499c..5beca05afca98 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -5,6 +5,7 @@ trigger: - main-vs-deps - release/dev16.*-vs-deps - release/dev17.* + - features/lsp_tools_host exclude: - release/dev17.0 pr: none From a45697e309115801276d551cee99a2a11e8ebf23 Mon Sep 17 00:00:00 2001 From: Arun Chander Date: Thu, 9 Mar 2023 10:22:52 -0800 Subject: [PATCH 058/261] Cherrypicking minor tweaks to logging and brokering unregister --- .../BrokeredServices/BrokeredServiceContainer.cs | 5 +++++ .../HostWorkspace/LanguageServerProjectSystem.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs index 957255ba110d2..789b9a89c9210 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceContainer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; @@ -26,6 +27,10 @@ public BrokeredServiceContainer(TraceSource traceSource) internal new void RegisterServices(IReadOnlyDictionary services) => base.RegisterServices(services); + /// + internal new void UnregisterServices(IEnumerable services) + => base.UnregisterServices(services); + internal ImmutableDictionary GetRegisteredServices() => RegisteredServices; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index df0a2686253ec..4d44e2499bbee 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -83,8 +83,8 @@ public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray a { if (File.Exists(analyzerPath)) { - _logger.LogWarning($"Solution-level analyzer at {analyzerPath} added to workspace."); references.Add(new AnalyzerFileReference(analyzerPath, analyzerLoader)); + _logger.LogInformation($"Solution-level analyzer at {analyzerPath} added to workspace."); } else { From 8e44926a39e6cfeebf99cae7109d8b55d273e4cd Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 9 Mar 2023 15:36:23 -0800 Subject: [PATCH 059/261] Disable colors in console logger to prevent outputting control characters on linux --- .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 35a9b638f3a5c..83dc5fa44ad72 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; var parser = CreateCommandLineParser(); @@ -38,6 +39,8 @@ static async Task RunAsync(bool launchDebugger, string? solutionPath, string? br { builder.SetMinimumLevel(minimumLogLevel); builder.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace); + // The console logger outputs control characters on unix for colors which don't render correctly in VSCode. + builder.AddSimpleConsole(formatterOptions => formatterOptions.ColorBehavior = LoggerColorBehavior.Disabled); }) )); }); From b0364f7e83dea6db7b2a34737356971fc556e32d Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 14 Mar 2023 19:00:31 -0700 Subject: [PATCH 060/261] Update test to assert less errors --- .../ExportProviderBuilder.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 8d195857e4bde..cb87eceea2299 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -51,19 +51,13 @@ private static void ThrowOnUnexpectedErrors(CompositionConfiguration configurati // Verify that we have exactly the MEF errors that we expect. If we have less or more this needs to be updated to assert the expected behavior. // Currently we are expecting the following: // "----- CompositionError level 1 ------ - // Microsoft.CodeAnalysis.CSharp.CodeRefactorings.AddMissingImports.CSharpAddMissingImportsRefactoringProvider.ctor(pasteTrackingService): expected exactly 1 export matching constraints: - // Contract name: Microsoft.CodeAnalysis.PasteTracking.IPasteTrackingService - // TypeIdentityName: Microsoft.CodeAnalysis.PasteTracking.IPasteTrackingService - // but found 0. - // part definition Microsoft.CodeAnalysis.CSharp.CodeRefactorings.AddMissingImports.CSharpAddMissingImportsRefactoringProvider - // Microsoft.CodeAnalysis.ExternalAccess.Pythia.PythiaSignatureHelpProvider.ctor(implementation): expected exactly 1 export matching constraints: // Contract name: Microsoft.CodeAnalysis.ExternalAccess.Pythia.Api.IPythiaSignatureHelpProviderImplementation // TypeIdentityName: Microsoft.CodeAnalysis.ExternalAccess.Pythia.Api.IPythiaSignatureHelpProviderImplementation // but found 0. // part definition Microsoft.CodeAnalysis.ExternalAccess.Pythia.PythiaSignatureHelpProvider var erroredParts = configuration.CompositionErrors.FirstOrDefault()?.SelectMany(error => error.Parts).Select(part => part.Definition.Type.Name) ?? Enumerable.Empty(); - var expectedErroredParts = new string[] { "CSharpAddMissingImportsRefactoringProvider", "PythiaSignatureHelpProvider" }; + var expectedErroredParts = new string[] { "PythiaSignatureHelpProvider" }; if (erroredParts.Count() != expectedErroredParts.Length || !erroredParts.All(part => expectedErroredParts.Contains(part))) { configuration.ThrowOnErrors(); From 50828e44fef7244249ef200ea9668e7aa82b16fe Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 14 Mar 2023 22:42:11 -0700 Subject: [PATCH 061/261] Update comment Make the comment match the code better, and also explain the scenario it's thinking about. --- .../Portable/Workspace/ProjectSystem/IFileChangeWatcher.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/IFileChangeWatcher.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/IFileChangeWatcher.cs index 358b4ed163703..cb50ef1b30cc4 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/IFileChangeWatcher.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/IFileChangeWatcher.cs @@ -27,8 +27,8 @@ internal sealed class WatchedDirectory { public WatchedDirectory(string path, string? extensionFilter) { - // We are doing string comparisons with this path, so ensure it has a trailing \ so we don't get confused with sibling - // paths that won't actually be covered. + // We are doing string comparisons with this path, so ensure it has a trailing directory separator so we don't get confused with sibling + // paths that won't actually be covered. For example, if we're watching C:\Directory we wouldn't see changes to C:\DirectorySibling\Foo.txt. if (!path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString())) { path += System.IO.Path.DirectorySeparatorChar; From 2024d09603fa180272ef2ea5a030743d400e03dc Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 14 Mar 2023 22:46:54 -0700 Subject: [PATCH 062/261] Watch some places where we put reference assemblies on Unix Generally, the language service is simply given a list of source files or reference assemblies, and we have to watch all of them in case any of them were to change. One problem we run into is we just get files without any real sense of structure, and this can lead to inefficiencies. For example, for reference assemblies, if we're given a list of reference assemblies, we can naively add each file to a list to watch, but at some point we either have to transition to a directory watch for efficiency. And although we can do that, it's still time being spent during a solution load when we can be doing better things. One optimization we do on Windows is we know there are certain folders where we're likely to get lots of references, but the folder is unlikely to have many changes, so there's no real downside to just watching the entire directory at once. For example, on Windows the .NET Framework reference assemblies folder we can just stick a file watch on at the very beginning, and then know we never have to watch any individual file under that directory for the rest of the process. This extends that optimization to Linux/Mac as well. --- ...ileWatchedPortableExecutableReferenceFactory.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/FileWatchedPortableExecutableReferenceFactory.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/FileWatchedPortableExecutableReferenceFactory.cs index a49d837f98f6a..769402ce287f9 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/FileWatchedPortableExecutableReferenceFactory.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/FileWatchedPortableExecutableReferenceFactory.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; @@ -44,13 +45,22 @@ internal sealed class FileWatchedPortableExecutableReferenceFactory var watchedDirectories = new List(); + // On each platform, there is a place that reference assemblies for the framework are installed. These are rarely going to be changed + // but are the most common places that we're going to create file watches. Rather than either creating a huge number of file watchers + // for every single file, or eventually realizing we should just watch these directories, we just create the single directory watchers now. if (PlatformInformation.IsWindows) { - // We will do a single directory watch on the Reference Assemblies folder to avoid having to create separate file - // watches on individual .dlls that effectively never change. var referenceAssembliesPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Reference Assemblies", "Microsoft", "Framework"); watchedDirectories.Add(new WatchedDirectory(referenceAssembliesPath, ".dll")); } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + watchedDirectories.Add(new WatchedDirectory("/usr/lib/dotnet/packs", ".dll")); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + watchedDirectories.Add(new WatchedDirectory("/usr/local/share/dotnet/packs", ".dll")); + } // TODO: set this to watch the NuGet directory as well; there's some concern that watching the entire directory // might make restores take longer because we'll be watching changes that may not impact your project. From 88eb71ebac07ce4deba3add0a4115c14af7533eb Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Thu, 16 Mar 2023 13:45:21 -0700 Subject: [PATCH 063/261] Handle the underlying file watcher being null When I originally implemented our file watcher logic, I added a hack to deal with trying to watch a file when the entire directory is missing. The Dispose() method didn't handle that case though, and assumed the file watcher would still be created. This fixes that oversight. Fixes https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1773122 --- .../HostWorkspace/FileChangeWatcher.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs index 6ef9a71e3e7fe..f1dfc9fa56666 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileChangeWatcher.cs @@ -154,9 +154,8 @@ public IndividualWatchedFile(string filePath, FileChangeContext context) public void Dispose() { - if (_context._individualWatchedFiles.Remove(this)) + if (_context._individualWatchedFiles.Remove(this) && _watcher != null) { - Contract.ThrowIfNull(_watcher); _watcher.Changed -= _context.RaiseEvent; _watcher.Created -= _context.RaiseEvent; _watcher.Deleted -= _context.RaiseEvent; From 2e5e3a3a7c0a92dce55de28b934eecd73a3c92f7 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 16 Mar 2023 14:43:55 -0700 Subject: [PATCH 064/261] Workaround runtime bug in 7.0.4 where MEF assembly load APIs fail --- .../ExportProviderBuilder.cs | 11 +++++++++++ .../Microsoft.CodeAnalysis.LanguageServer.csproj | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index cb87eceea2299..c924069a54170 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Reflection; +using System.Runtime.Loader; using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -20,6 +21,16 @@ public static async Task CreateExportProviderAsync() var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll"); assembliesToDiscover = assembliesToDiscover.Concat(Directory.EnumerateFiles(baseDirectory, "Microsoft.ServiceHub*.dll")); + // Temporarily explicitly load the dlls we want to add to the MEF composition. This is due to a runtime bug + // in the 7.0.4 runtime where the APIs MEF uses to load assemblies break with R2R assemblies. + // See https://github.com/dotnet/runtime/issues/83526 + // + // Once a newer version of the runtime is widely available, we can remove this. + foreach (var path in assembliesToDiscover) + { + Assembly.LoadFrom(path); + } + var discovery = PartDiscovery.Combine( new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) new AttributedPartDiscoveryV1(Resolver.DefaultInstance)); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index bffb24e4602a5..99f1d0d777520 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -37,7 +37,7 @@ win-x64;win-x86;win-arm64;linux-x64;linux-arm64;alpine-x64;alpine-arm64;osx-x64;osx-arm64 - true + true From 6f87e25e09d3718fe711dfaf53c33e4ee9437e80 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 17 Mar 2023 18:04:30 -0700 Subject: [PATCH 065/261] Add alternative wait for debugger implementation for non-windows systems --- .../Program.cs | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 83dc5fa44ad72..a93029b89a335 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -7,6 +7,7 @@ using System.CommandLine.Builder; using System.CommandLine.Parsing; using System.Diagnostics; +using System.Runtime.InteropServices; using Microsoft.Build.Locator; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; @@ -23,11 +24,6 @@ static async Task RunAsync(bool launchDebugger, string? solutionPath, string? brokeredServicePipeName, LogLevel minimumLogLevel, CancellationToken cancellationToken) { - if (launchDebugger) - { - _ = Debugger.Launch(); - } - // Before we initialize the LSP server we can't send LSP log messages. // Create a console logger as a fallback to use before the LSP server starts. using var loggerFactory = LoggerFactory.Create(builder => @@ -45,6 +41,27 @@ static async Task RunAsync(bool launchDebugger, string? solutionPath, string? br )); }); + if (launchDebugger) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Debugger.Launch() only works on Windows. + _ = Debugger.Launch(); + } + else + { + var logger = loggerFactory.CreateLogger(); + var timeout = TimeSpan.FromMinutes(1); + logger.LogInformation($"Server started with process ID {Environment.ProcessId}"); + logger.LogInformation($"Waiting {timeout:g} for a debugger to attach"); + using var timeoutSource = new CancellationTokenSource(timeout); + while (!Debugger.IsAttached && !timeoutSource.Token.IsCancellationRequested) + { + await Task.Delay(100, CancellationToken.None); + } + } + } + // Register and load the appropriate MSBuild assemblies before we create the MEF composition. // This is required because we need to include types from MS.CA.Workspaces.MSBuild which has a dependency on MSBuild dlls being loaded. var msbuildDiscoveryOptions = new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.DotNetSdk }; From 233f9edc6705eaccf1648d9bed208cba1644e904 Mon Sep 17 00:00:00 2001 From: Larissa Cox Date: Mon, 20 Mar 2023 20:45:25 +0000 Subject: [PATCH 066/261] Merged PR 29952: IntelliCode: Enable Starred Suggestions - enabling starred suggestions when VS Green is available - added helper class for finding and loading starred suggestions dll and retrieving necessary completion provider - added MEF completion provider, which is initialized by MEF and calls into inner completion provider to get starred suggestions - updated Program.cs to take in starred suggestions info and initialize helper classes - updated Descriptors.cs to register starred suggestions brokered service --- eng/Versions.props | 4 +- .../AbstractLanguageServerProtocolTests.cs | 4 +- .../BrokeredServices/Services/Descriptors.cs | 2 + .../Program.cs | 16 ++- .../CSharpStarredCompletionProvider.cs | 41 ++++++ .../StarredCompletionsAssemblyHelper.cs | 121 ++++++++++++++++++ .../ILspCompletionResultCreationService.cs | 4 +- .../Completion/CompletionTests.cs | 18 +-- 8 files changed, 193 insertions(+), 17 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/CSharpStarredCompletionProvider.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs diff --git a/eng/Versions.props b/eng/Versions.props index c1dce8b424399..494cde2bea8bb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -25,14 +25,14 @@ 0.1.149-beta 4.3.0-1.final - 17.5.274-preview + 17.6.76-preview $(VisualStudioEditorPackagesVersion) 6.0.0-rtm.21518.12 6.0.0-rtm.21518.12 17.3.3101 - 17.6.4-preview + 17.6.16-preview 17.6.35295-preview.2 16.10.0 - + diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index 63f6cf2df5ad0..825c3b29460a7 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -57,8 +57,8 @@ - - + + diff --git a/src/Workspaces/Core/MSBuild/MSBuild/Constants/PropertyNames.cs b/src/Workspaces/Core/MSBuild/MSBuild/Constants/PropertyNames.cs index 2691c30f7e5e5..84fadee0836c9 100644 --- a/src/Workspaces/Core/MSBuild/MSBuild/Constants/PropertyNames.cs +++ b/src/Workspaces/Core/MSBuild/MSBuild/Constants/PropertyNames.cs @@ -60,6 +60,7 @@ internal static class PropertyNames public const string TargetCompactFramework = nameof(TargetCompactFramework); public const string TargetFramework = nameof(TargetFramework); public const string TargetFrameworks = nameof(TargetFrameworks); + public const string TargetFrameworkIdentifier = nameof(TargetFrameworkIdentifier); public const string TargetPath = nameof(TargetPath); public const string TargetRefPath = nameof(TargetRefPath); public const string TreatWarningsAsErrors = nameof(TreatWarningsAsErrors); diff --git a/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFile.cs b/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFile.cs index 62c2ac0ad3ad4..708e01d35a78e 100644 --- a/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFile.cs +++ b/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFile.cs @@ -146,6 +146,8 @@ private ProjectFileInfo CreateProjectFileInfo(MSB.Execution.ProjectInstance proj targetFramework = null; } + var targetFrameworkIdentifier = project.ReadPropertyString(PropertyNames.TargetFrameworkIdentifier); + var docs = project.GetDocuments() .Where(IsNotTemporaryGeneratedFile) .Select(MakeDocumentFileInfo) @@ -167,6 +169,7 @@ private ProjectFileInfo CreateProjectFileInfo(MSB.Execution.ProjectInstance proj intermediateOutputFilePath, defaultNamespace, targetFramework, + targetFrameworkIdentifier, commandLineArgs, docs, additionalDocs, diff --git a/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFileInfo.cs b/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFileInfo.cs index 561322651a523..71128b114258b 100644 --- a/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFileInfo.cs +++ b/src/Workspaces/Core/MSBuild/MSBuild/ProjectFile/ProjectFileInfo.cs @@ -62,6 +62,12 @@ internal sealed class ProjectFileInfo /// public string? TargetFramework { get; } + /// + /// The target framework identifier of this project. + /// Used to determine if a project is targeting .net core. + /// + public string? TargetFrameworkIdentifier { get; } + /// /// The command line args used to compile the project. /// @@ -107,6 +113,7 @@ public override string ToString() string? intermediateOutputFilePath, string? defaultNamespace, string? targetFramework, + string? targetFrameworkIdentifier, ImmutableArray commandLineArgs, ImmutableArray documents, ImmutableArray additionalDocuments, @@ -124,6 +131,7 @@ public override string ToString() this.IntermediateOutputFilePath = intermediateOutputFilePath; this.DefaultNamespace = defaultNamespace; this.TargetFramework = targetFramework; + this.TargetFrameworkIdentifier = targetFrameworkIdentifier; this.CommandLineArgs = commandLineArgs; this.Documents = documents; this.AdditionalDocuments = additionalDocuments; @@ -140,6 +148,7 @@ public override string ToString() string? intermediateOutputFilePath, string? defaultNamespace, string? targetFramework, + string? targetFrameworkIdentifier, ImmutableArray commandLineArgs, ImmutableArray documents, ImmutableArray additionalDocuments, @@ -155,6 +164,7 @@ public override string ToString() intermediateOutputFilePath, defaultNamespace, targetFramework, + targetFrameworkIdentifier, commandLineArgs, documents, additionalDocuments, @@ -172,6 +182,7 @@ public static ProjectFileInfo CreateEmpty(string language, string? filePath, Dia intermediateOutputFilePath: null, defaultNamespace: null, targetFramework: null, + targetFrameworkIdentifier: null, commandLineArgs: ImmutableArray.Empty, documents: ImmutableArray.Empty, additionalDocuments: ImmutableArray.Empty, From d8d34c8efa97078e023b2a0664e444dded72f76f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 28 Mar 2023 09:15:41 -0700 Subject: [PATCH 122/261] Take same lock as ProjectSystemProjectFactory --- .../LanguageServerProjectSystem.cs | 4 ++- .../HostWorkspace/LanguageServerWorkspace.cs | 26 +++++++++++++++---- .../ProjectSystemProjectFactory.cs | 4 +-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index 4d44e2499bbee..717318b02cb46 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -47,8 +47,10 @@ internal sealed class LanguageServerProjectSystem IAsynchronousOperationListenerProvider listenerProvider) { _logger = loggerFactory.CreateLogger(nameof(LanguageServerProjectSystem)); - Workspace = new LanguageServerWorkspace(hostServicesProvider.HostServices); + var workspace = new LanguageServerWorkspace(hostServicesProvider.HostServices); + Workspace = workspace; ProjectSystemProjectFactory = new ProjectSystemProjectFactory(Workspace, new FileChangeWatcher(), static (_, _) => Task.CompletedTask, _ => { }); + workspace.ProjectSystemProjectFactory = ProjectSystemProjectFactory; analyzerLoader.InitializeDiagnosticsServices(Workspace); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs index 93062f995237b..cc4e4594edf48 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; @@ -38,6 +39,12 @@ namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; /// internal class LanguageServerWorkspace : Workspace, ILspWorkspace { + /// + /// Will be set by LanguageServerProjectSystem immediately after creating this instance. Can't be passed into the + /// constructor as the factory needs a reference to this type. + /// + public ProjectSystemProjectFactory ProjectSystemProjectFactory { private get; set; } = null!; + public LanguageServerWorkspace( HostServices host) : base(host, WorkspaceKind.Host) @@ -48,9 +55,18 @@ internal class LanguageServerWorkspace : Workspace, ILspWorkspace bool ILspWorkspace.SupportsMutation => true; - void ILspWorkspace.UpdateTextIfPresent(DocumentId documentId, SourceText sourceText) - => OnDocumentTextChanged(documentId, sourceText, PreservationMode.PreserveIdentity, requireDocumentPresent: false); - - void ILspWorkspace.UpdateTextIfPresent(DocumentId documentId, TextLoader textLoader) - => OnDocumentTextLoaderChanged(documentId, textLoader, requireDocumentPresent: false); + ValueTask ILspWorkspace.UpdateTextIfPresentAsync(DocumentId documentId, SourceText sourceText, CancellationToken cancellationToken) + { + // We need to ensure that our changes, and the changes made by the ProjectSystemProjectFactory don't interleave. + // Specifically, ProjectSystemProjectFactory often makes several changes in a row that it thinks cannot be + // interrupted. To ensure this, we call into ProjectSystemProjectFactory to synchronize on the same lock that + // it has when making workspace changes. + // + // https://github.com/dotnet/roslyn/issues/67510 tracks cleaning up ProjectSystemProjectFactory so that it + // shares the same sync/lock/application code with the core workspace code. Once that happens, we won't need + // to do special coordination here. + return this.ProjectSystemProjectFactory.ApplyChangeToWorkspaceAsync( + _ => this.OnDocumentTextChanged(documentId, sourceText, PreservationMode.PreserveIdentity, requireDocumentPresent: false), + cancellationToken); + } } diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs index 07bae911edb29..dcc88ff2594f3 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs @@ -174,9 +174,9 @@ public void ApplyChangeToWorkspace(Action action) /// /// Applies a single operation to the workspace. should be a call to one of the protected Workspace.On* methods. /// - public async ValueTask ApplyChangeToWorkspaceAsync(Action action) + public async ValueTask ApplyChangeToWorkspaceAsync(Action action, CancellationToken cancellationToken = default) { - using (await _gate.DisposableWaitAsync().ConfigureAwait(false)) + using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { action(Workspace); } From fb93453d67a8723398fd785639098eeda6df53bf Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 28 Mar 2023 14:59:19 -0700 Subject: [PATCH 123/261] Review feedback --- .../HostWorkspace/LanguageServerProjectSystem.cs | 2 -- .../WorkspaceDebugConfigurationHandler.cs | 6 +----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs index 9e357c92ab282..7ab6dfc5b8a98 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectSystem.cs @@ -105,8 +105,6 @@ public void OpenSolution(string solutionFilePath) var solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(solutionFilePath); - ProjectSystemProjectFactory.SolutionPath = solutionFilePath; - foreach (var project in solutionFile.ProjectsInOrder) { if (project.ProjectType == Microsoft.Build.Construction.SolutionProjectType.SolutionFolder) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationHandler.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationHandler.cs index 4e6e7c953fdbd..e20b485a82491 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationHandler.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationHandler.cs @@ -45,11 +45,7 @@ public Task HandleRequestAsync(WorkspaceDebugConfig private static bool IsProjectInWorkspace(Uri workspacePath, Project project) { - var relativePath = Path.GetRelativePath(workspacePath.LocalPath, project.FilePath!); - // The project is in contained in the workspace path if the relative path is not above the workspace path and the relative path is not rooted. - return relativePath != ".." && - !(relativePath.StartsWith("../") || relativePath.StartsWith(@"..\")) && - !Path.IsPathRooted(relativePath); + return PathUtilities.IsSameDirectoryOrChildOf(project.FilePath!, workspacePath.LocalPath); } private ProjectDebugConfiguration GetProjectDebugConfiguration(Project project) From b494f084f1856521f80aabe09f3181dd0e76ab34 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 28 Mar 2023 23:02:09 -0700 Subject: [PATCH 124/261] Fix removal of dymamic files --- .../HostWorkspace/LoadedProject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs index 96d814814f9ca..7640528ccf351 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LoadedProject.cs @@ -132,7 +132,7 @@ public async ValueTask UpdateWithNewProjectInfoAsync(ProjectFileInfo newProjectI _mostRecentFileInfo?.AdditionalDocuments.Where(TreatAsIsDynamicFile).Distinct(DocumentFileInfoComparer.Instance), DocumentFileInfoComparer.Instance, document => _projectSystemProject.AddDynamicSourceFile(document.FilePath, folders: ImmutableArray.Empty), - document => _projectSystemProject.RemoveAdditionalFile(document.FilePath)); + document => _projectSystemProject.RemoveDynamicSourceFile(document.FilePath)); _mostRecentFileInfo = newProjectInfo; From 759fe7e953d8c128e84ceaba1c382e9a8e324a65 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Thu, 30 Mar 2023 20:37:54 +0000 Subject: [PATCH 125/261] Merged PR 30283: Add telemetry MEF import for VS Dev kit Gets us publishing an npm package that will be added as a component to VS Dev kit. Left to do: * [ ] Import the new service in LSP * [ ] Make changes to VS Dev kit repo to add component * [ ] Add integration tests in VS Dev kit --- Roslyn.sln | 7 ++ azure-pipelines-official.yml | 13 +++ eng/Versions.props | 1 + eng/build.ps1 | 11 ++ eng/config/.npmrc | 2 + eng/config/PublishData.json | 11 ++ eng/publish-assets.ps1 | 33 ++++++ eng/targets/Settings.props | 6 ++ .../VSCode/API/VSCodeTelemetryLogger.cs | 53 --------- .../Protocol/ILspFaultLogger.cs | 14 +++ ...odeAnalysis.LanguageServer.Protocol.csproj | 1 + ...isualStudio.LanguageServer.Internal.csproj | 45 ++++++++ .../VSCodeTelemetryLogger.cs | 101 ++++++++++++++++++ .../package.json | 4 + .../Microsoft.CodeAnalysis.Workspaces.csproj | 1 + ...soft.CodeAnalysis.Remote.ServiceHub.csproj | 1 + 16 files changed, 251 insertions(+), 53 deletions(-) create mode 100644 eng/config/.npmrc delete mode 100644 src/Features/LanguageServer/Protocol/ExternalAccess/VSCode/API/VSCodeTelemetryLogger.cs create mode 100644 src/Features/LanguageServer/Protocol/ILspFaultLogger.cs create mode 100644 src/VisualStudio/Microsoft.VisualStudio.LanguageServer.Internal/Microsoft.VisualStudio.LanguageServer.Internal.csproj create mode 100644 src/VisualStudio/Microsoft.VisualStudio.LanguageServer.Internal/VSCodeTelemetryLogger.cs create mode 100644 src/VisualStudio/Microsoft.VisualStudio.LanguageServer.Internal/package.json diff --git a/Roslyn.sln b/Roslyn.sln index d57f7701a9f50..4d225dbb22842 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -533,6 +533,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Too EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LanguageServer", "LanguageServer", "{D449D505-CC6A-4E0B-AF1B-976E2D0AE67A}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServer.Internal", "src\VisualStudio\Microsoft.VisualStudio.LanguageServer.Internal\Microsoft.VisualStudio.LanguageServer.Internal.csproj", "{9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1303,6 +1305,10 @@ Global {521ADC3E-CC15-414B-9356-D87C5BCF3A24}.Debug|Any CPU.Build.0 = Debug|Any CPU {521ADC3E-CC15-414B-9356-D87C5BCF3A24}.Release|Any CPU.ActiveCfg = Release|Any CPU {521ADC3E-CC15-414B-9356-D87C5BCF3A24}.Release|Any CPU.Build.0 = Release|Any CPU + {9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1545,6 +1551,7 @@ Global {2A3C94F7-5B5E-4CDC-B645-672815E61DEB} = {D449D505-CC6A-4E0B-AF1B-976E2D0AE67A} {9A90AA02-4275-40ED-B1F1-731AF17E675C} = {D449D505-CC6A-4E0B-AF1B-976E2D0AE67A} {521ADC3E-CC15-414B-9356-D87C5BCF3A24} = {C52D8057-43AF-40E6-A01B-6CDBB7301985} + {9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00} = {8DBA5174-B0AA-4561-82B1-A46607697753} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29} diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index aaf421d64a7b7..59af2b0315cc1 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -135,11 +135,24 @@ stages: inputs: versionSpec: '4.9.2' + - task: NodeTool@0 + inputs: + versionSpec: '16.x' + displayName: 'Install Node.js' + # Authenticate with service connections to be able to publish packages to external nuget feeds. - task: NuGetAuthenticate@0 inputs: nuGetServiceConnections: azure-public/vs-impl, azure-public/vssdk, devdiv/engineering, devdiv/dotnet-core-internal-tooling + # Authenticates the .npmrc file for publishing to the internal AzDO feed. + # See: https://learn.microsoft.com/azure/devops/pipelines/tasks/package/npm-authenticate?view=azure-devops + - task: npmAuthenticate@0 + displayName: Authenticate NPM Feed + inputs: + workingFile: $(Build.SourcesDirectory)/eng/config/.npmrc + customEndpoint: devdiv-vs-green-npm-package-feed + # Needed for SBOM tool - task: UseDotNet@2 displayName: 'Use .NET Core 3.1 runtime' diff --git a/eng/Versions.props b/eng/Versions.props index f910bb8cfc906..d9d98c6c623a6 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -160,6 +160,7 @@ $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) + 2.0.93 17.6.0-preview-2-33427-043 $(VisualStudioEditorPackagesVersion) 15.8.27812-alpha diff --git a/eng/build.ps1 b/eng/build.ps1 index 322d3670aa033..f819482e1a783 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -261,6 +261,8 @@ function BuildSolution() { # https://github.com/NuGet/Home/issues/12373 $restoreUseStaticGraphEvaluation = if ($ci) { $false } else { $true } + $isNpmAvailable = IsNpmAvailable + MSBuild $toolsetBuildProj ` $bl ` /p:Configuration=$configuration ` @@ -282,6 +284,7 @@ function BuildSolution() { /p:RestoreUseStaticGraphEvaluation=$restoreUseStaticGraphEvaluation ` /p:VisualStudioIbcDrop=$ibcDropName ` /p:VisualStudioDropAccessToken=$officialVisualStudioDropAccessToken ` + /p:IsNpmPackable=$isNpmAvailable ` $suppressExtensionDeployment ` $msbuildWarnAsError ` $buildFromSource ` @@ -704,6 +707,14 @@ function List-Processes() { Get-Process -Name "devenv" -ErrorAction SilentlyContinue | Out-Host } +function IsNpmAvailable() { + if (Get-Command "npm" -ErrorAction SilentlyContinue) { + return $true + } + + return $false; +} + try { if ($PSVersionTable.PSVersion.Major -lt "5") { Write-Host "PowerShell version must be 5 or greater (version $($PSVersionTable.PSVersion) detected)" diff --git a/eng/config/.npmrc b/eng/config/.npmrc new file mode 100644 index 0000000000000..c750f7dcc0929 --- /dev/null +++ b/eng/config/.npmrc @@ -0,0 +1,2 @@ +registry=https://pkgs.dev.azure.com/devdiv/DevDiv/_packaging/vs-green/npm/registry/ +always-auth=true \ No newline at end of file diff --git a/eng/config/PublishData.json b/eng/config/PublishData.json index 46a375653ab30..b063d0909b9d6 100644 --- a/eng/config/PublishData.json +++ b/eng/config/PublishData.json @@ -42,6 +42,7 @@ "Microsoft.CodeAnalysis.EditorFeatures.Wpf": "vssdk", "Microsoft.CodeAnalysis.EditorFeatures.Cocoa": "vssdk", "Microsoft.VisualStudio.IntegrationTest.Utilities": "vs-impl", + "Microsoft.VisualStudio.LanguageServer.Internal": "npm", "Microsoft.CodeAnalysis.LanguageServer.Protocol": "vs-impl", "Microsoft.CodeAnalysis.CSharp.LanguageServer.Protocol": "vs-impl", "Microsoft.CodeAnalysis.VisualBasic.LanguageServer.Protocol": "vs-impl", @@ -186,6 +187,16 @@ "vsMajorVersion": 17, "insertionCreateDraftPR": true, "insertionTitlePrefix": "[Validation]" + }, + "dev/andrha/telemetry": { + "nugetKind": [ + "Shipping", + "NonShipping" + ], + "vsBranch": "main", + "vsMajorVersion": 17, + "insertionCreateDraftPR": true, + "insertionTitlePrefix": "[Telemetry Validation]" } } } diff --git a/eng/publish-assets.ps1 b/eng/publish-assets.ps1 index b81ee6b7ded1a..d1bac5b4d252c 100644 --- a/eng/publish-assets.ps1 +++ b/eng/publish-assets.ps1 @@ -93,6 +93,11 @@ function Publish-Nuget($publishData, [string]$packageDir) { continue } + if ($feedName.equals("npm")) { + Write-Host "Skipping publishing for $nupkg as it is published as an NPM package" + continue + } + # Use the feed name to get the source to upload the package to. if (-not (Get-Member -InputObject $feedData -Name $feedName)) { throw "$feedName has no configured source feed" @@ -102,6 +107,7 @@ function Publish-Nuget($publishData, [string]$packageDir) { $apiKey = Get-PublishKey $uploadUrl if (-not $test) { + Write-Host "Publishing $nupkg" Exec-Console $dotnet "nuget push $nupkg --source $uploadUrl --api-key $apiKey" } } @@ -111,6 +117,30 @@ function Publish-Nuget($publishData, [string]$packageDir) { } } +function Publish-Npm([string]$npmPackagesDir) { + Write-Host "" + Write-Host "Publishing NPM packages in $npmPackagesDir..." + + $npmrcPath = [IO.Path]::Combine($RepoRoot, "eng", "config", ".npmrc") + if (-not (Test-Path $npmrcPath)) { + throw "Missing .npmrc at $npmrcPath" + } + + foreach ($npmPackage in Get-ChildItem -Path (Join-Path $npmPackagesDir "*") -Include *.tgz) { + Write-Host "" + + $publishCommandArgs = "npm publish --dryrun --userconfig ""$npmrcPath"" ""$npmPackage""" + Write-Host "Publishing $npmPackage" + $publishOutput = & cmd /c "$publishCommandArgs" + if ($LastExitCode -ne 0) + { + Write-Host "##vso[task.logissue type=error]An error occurred while publishing '$npmPackage'." + Write-Host $publishOutput + throw + } + } +} + # Do basic verification on the values provided in the publish configuration function Test-Entry($publishData, [switch]$isBranch) { if ($isBranch) { @@ -131,6 +161,9 @@ function Publish-Entry($publishData, [switch]$isBranch) { Publish-NuGet $publishData (Join-Path $PackagesDir $nugetKind) } + # Publish any NPM packages to the specified feed + Publish-NPM (Join-Path $PackagesDir "NPM") + exit 0 } diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index 0362d4e964ae3..4393dafc69e2a 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -51,6 +51,11 @@ false false true + + + $(ArtifactsDir)\packages\$(Configuration)\NPM\ + + false - 3.3.5-beta1.23180.2 + 3.3.5-beta1.23181.1 8.0.0-preview.23180.2 1.1.2-beta1.23163.2 0.1.149-beta @@ -224,7 +224,7 @@ is expected by the NET SDK used in the Workspace.MSBuild UnitTests. In order to test against the same verion of NuGet as our configured SDK, we must set the version to be the same. --> - 6.4.0-rc.117 + 6.6.0-preview.3.57 $(NuGetCommonVersion) $(NuGetCommonVersion) $(NuGetCommonVersion) diff --git a/eng/config/PublishData.json b/eng/config/PublishData.json index 6cd19f132f3f7..3df62fd787481 100644 --- a/eng/config/PublishData.json +++ b/eng/config/PublishData.json @@ -144,18 +144,9 @@ "Shipping", "NonShipping" ], - "vsBranch": "main", + "vsBranch": "rel/d17.6", "vsMajorVersion": 17, "insertionTitlePrefix": "[d17.6P3]" - }, - "release/dev17.7-vs-deps": { - "nugetKind": [ - "Shipping", - "NonShipping" - ], - "vsBranch": "rel/d17.7", - "vsMajorVersion": 17, - "insertionTitlePrefix": "[d17.7P1]" }, "main": { "nugetKind": [ @@ -165,17 +156,7 @@ "vsBranch": "main", "vsMajorVersion": 17, "insertionCreateDraftPR": true, - "insertionTitlePrefix": "[Validation]" - }, - "main-vs-deps": { - "nugetKind": [ - "Shipping", - "NonShipping" - ], - "vsBranch": "main", - "vsMajorVersion": 17, - "insertionCreateDraftPR": true, - "insertionTitlePrefix": "[Validation]" + "insertionTitlePrefix": "[d17.7P1]" }, "dev/jorobich/fix-pr-val": { "nugetKind": [ diff --git a/global.json b/global.json index 9edd9ee432ec2..aa76203043e47 100644 --- a/global.json +++ b/global.json @@ -15,4 +15,4 @@ "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23168.1", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23168.1" } -} +} \ No newline at end of file diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf index db6f381d30afb..7bc3956c9308b 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Nastavit člena jako readonly {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Člena je možné nastavit jako readonly {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf index 42ac12a8da0aa..5a1db32dacb64 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Member als "readonly" festlegen {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Member kann als "readonly" festgelegt werden {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf index 224f7ad65d8c0..51521cb68b54c 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Convertir el miembro en 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + El miembro se puede hacer "readonly" {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf index 2aeff278de227..87c19b25143e8 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Définir comme membre 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Le membre peut être défini en 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf index 92d5a8814d6ea..6bb23e8a9f7c6 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Rendi il membro 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Il membro può essere impostato come 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf index dba393987ecfb..b74131b1fd701 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + メンバーを 'readonly' にする {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + メンバーを 'readonly' にすることができます {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf index 048612caf9ea3..2b4da82f62e64 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + 멤버를 'readonly'로 만들기 {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + 멤버를 'readonly'로 만들 수 있음 {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf index 0e3e6fc597d82..91477a8a231d1 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Ustaw element członkowski jako „readonly” {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Element członkowski można określić jako „readonly” {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf index 4716a15472ae8..2b0e9282966f9 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Tornar membro 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + O membro pode se tornar 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf index 284bd174806a2..5c3344eb25c88 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Сделать элемент "readonly" {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Элемент можно сделать "readonly" {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf index 215375e4c025c..39c12f03d679a 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + Üyeyi 'readonly' yap {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + Üye 'readonly' yapılabilir {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf index f8ebcf4a4e9cb..d7fa9b2f91ab7 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + 将成员设为“readonly” {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + 可将成员设为“readonly” {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf index bf1c4a2d3c4f4..fc2c87c697226 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf @@ -94,7 +94,7 @@ Make member 'readonly' - Make member 'readonly' + 讓成員 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. @@ -104,7 +104,7 @@ Member can be made 'readonly' - Member can be made 'readonly' + 成員可以設為 'readonly' {Locked="readonly"} "readonly" is a C# keyword and should not be localized. diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf index 5ce994cd35ec8..ed160b4e29b97 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Přidat závorky @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Povolit v tomto projektu nezabezpečený kód Assign 'out' parameters - Assign 'out' parameters + Přiřadit parametry out {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Přiřadit parametry out (při spuštění) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Převést na poziční záznam(record) {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + Nastavit, že {0} má místo hodnoty typu Void vracet hodnotu Task Make field 'required' - Make field 'required' + Nastavit pole jako „required“ {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Převést metodu na asynchronní Make method async (stay void) - Make method async (stay void) + Převést metodu na asynchronní (ponechat neplatné) Make property 'required' - Make property 'required' + Nastavit vlastnost jako „required“ {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Nastavit jako ref struct {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Odebrat klíčové slovo in {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Odebrat modifikátor new @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Odebrat nepoužitou funkci @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Upgradovat všechny projekty jazyka C# na jazykovou verzi {0} Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Upgradovat tento projekt na jazykovou verzi C# {0} Use '{0}' - Use '{0}' + Použít {0} diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf index ab638db0e7470..db0b08309dbaa 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Klammern hinzufügen @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Unsicheren Code in diesem Projekt zulassen Assign 'out' parameters - Assign 'out' parameters + out-Parameter zuweisen {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + out-Parameter zuweisen (beim Start) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + In positionellen record konvertieren {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + "{0}" in Rückgabeaufgabe umwandeln, statt leer zu lassen. Make field 'required' - Make field 'required' + Feld als 'required' festlegen {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Methode als asynchron definieren Make method async (stay void) - Make method async (stay void) + Methode als asynchron definieren ("void" beibehalten) Make property 'required' - Make property 'required' + Eigenschaft als 'required' festlegen {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + "ref struct" erstellen {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Schlüsselwort "in" entfernen {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + new-Modifizierer entfernen @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Nicht verwendete Funktion entfernen @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Upgrade für alle C#-Projekte auf Sprachversion "{0}" durchführen Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Upgrade für dieses Projekt auf C#-Sprachversion "{0}" durchführen Use '{0}' - Use '{0}' + "{0}" verwenden diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf index d3da076647bb2..d938c4a4a8651 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Agregar paréntesis @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Permitir código no seguro en este proyecto Assign 'out' parameters - Assign 'out' parameters + Asignar parámetros "out" {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Asignar parámetros "out" (al inicio) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Convertir a positional record {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + Hacer que {0} devuelva Tarea en lugar de void. Make field 'required' - Make field 'required' + Convertir el campo en "required" {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Convertir el método en asincrónico Make method async (stay void) - Make method async (stay void) + Convertir método en asincónico (permanecer nulo) Make property 'required' - Make property 'required' + Convertir la propiedad en ''required'' {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Convertir "ref struct" {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Quitar la palabra clave "in" {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Quitar el modificador "new" @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Quitar función no utilizada @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Actualizar todos los proyectos de C# a la versión del lenguaje "{0}" Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Actualizar este proyecto a la versión del lenguaje de C# "{0}" Use '{0}' - Use '{0}' + Usar "{0}" diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf index 803d84e587376..c371305025a16 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Ajouter des parenthèses @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Autoriser du code unsafe dans ce projet Assign 'out' parameters - Assign 'out' parameters + Assigner des paramètres 'out' {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Assigner des paramètres 'out' (au début) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Convertir en record positionnel {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + {0} doit retourner Task au lieu de void. Make field 'required' - Make field 'required' + Rendre le champ 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Rendre la méthode async Make method async (stay void) - Make method async (stay void) + Rendre la méthode asynchrone (rester void) Make property 'required' - Make property 'required' + Définir la propriété 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Définir 'ref struct' {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Supprimer le mot clé 'in' {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Supprimer le modificateur 'new' @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Supprimer la fonction inutilisée @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Mettre à niveau tous les projets C# vers la version de langage '{0}' Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Mettre à niveau ce projet vers la version de langage C# '{0}' Use '{0}' - Use '{0}' + Utiliser '{0}' diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf index abd1fced89a75..4f09c1a7ff7b7 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Aggiungi parentesi @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Consenti codice unsafe in questo progetto Assign 'out' parameters - Assign 'out' parameters + Assegnare parametri 'out' {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Assegnare parametri 'out' (all'inizio) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Convertire in record posizionale {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + Fa in modo che {0} restituisca Task invece di void. Make field 'required' - Make field 'required' + Imposta il campo come 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Rendi asincrono il metodo Make method async (stay void) - Make method async (stay void) + Rendi asincrono il metodo (lascia nullo) Make property 'required' - Make property 'required' + Imposta la proprietà come 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Imposta come 'ref struct' {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Rimuovi la parola chiave 'in' {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Rimuovi il modificatore 'new' @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Rimuovi funzione non usata @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Aggiorna tutti i progetti alla versione '{0}' del linguaggio C# Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Aggiorna questo progetto alla versione '{0}' del linguaggio C# Use '{0}' - Use '{0}' + Usa '{0}' diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf index 72978a4d1b905..8a03f7427681c 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + 括弧を追加します @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + このプロジェクトでアンセーフ コードを許可する Assign 'out' parameters - Assign 'out' parameters + 'out' パラメーターの割り当て {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + 'out' パラメーターの割り当て (開始時) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + 位置指定 record に変換 {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + {0} が void ではなくタスクを返すようにします。 Make field 'required' - Make field 'required' + フィールドを 'required' にする {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + メソッドを非同期にします Make method async (stay void) - Make method async (stay void) + メソッドを非同期にする (void を維持) Make property 'required' - Make property 'required' + プロパティを 'required' にする {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + 'ref struct' を作成します {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + 'in' キーワードを削除します {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + 'new' 修飾子の削除 @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + 使用されていない関数を削除します @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + すべての C# プロジェクトを言語バージョン '{0}' にアップグレードする Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + このプロジェクトを C# 言語バージョン '{0}' にアップグレードする Use '{0}' - Use '{0}' + '{0}' を使用します diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf index 8d33b0bed7848..5a6937afd8ccb 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + 괄호 추가 @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + 이 프로젝트에서 안전하지 않은 코드 허용 Assign 'out' parameters - Assign 'out' parameters + 'out' 매개 변수 할당 {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + 'out' 매개 변수 할당(시작 시) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + 위치 record로 변환 {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + {0}에서 void 대신 Task를 반환하도록 설정합니다. Make field 'required' - Make field 'required' + 필드 'required' 만들기 {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + 메서드를 비동기로 설정 Make method async (stay void) - Make method async (stay void) + 메서드를 비동기로 설정(void 유지) Make property 'required' - Make property 'required' + 속성 'required' 만들기 {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + 'ref struct'로 지정 {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + 'in' 키워드 제거 {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + 'new' 한정자 제거 @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + 사용하지 않는 함수 제거 @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + 모든 C# 프로젝트를 언어 버전 '{0}'(으)로 업그레이드 Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + 이 프로젝트를 C# 언어 버전 '{0}'(으)로 업그레이드 Use '{0}' - Use '{0}' + '{0}' 사용 diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf index 470de4f1e44eb..f3ad412fe8ad6 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Dodaj nawiasy @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Zezwalaj na niebezpieczny kod w tym projekcie Assign 'out' parameters - Assign 'out' parameters + Przypisz parametry „out” {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Przypisz parametry „out” (na początku) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Konwertuj na pozycyjny record {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + Ustaw element {0}, aby zwracał zadanie zamiast elementu void. Make field 'required' - Make field 'required' + Ustaw pole jako „required” {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Ustaw metodę jako asynchroniczną Make method async (stay void) - Make method async (stay void) + Ustaw metodę jako asynchroniczną (pozostaw jako unieważnioną) Make property 'required' - Make property 'required' + Ustaw właściwość jako „required” {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Ustaw jako „ref struct” {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Usuń słowo kluczowe „in” {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Usuń modyfikator „new” @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Usuń nieużywaną funkcję @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Uaktualnij wszystkie projekty C# do wersji „{0}” języka Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Uaktualnij ten projekt do wersji „{0}” języka C# Use '{0}' - Use '{0}' + Użyj elementu „{0}” diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf index 32157d34017e1..a6efe5783fe32 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Adicionar parênteses @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Permitir código não seguro neste projeto Assign 'out' parameters - Assign 'out' parameters + Atribuir parâmetros 'out' {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Atribuir parâmetros 'out' (no início) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Converter em record posicional {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + Fazer com que {0} retorne Tarefa em vez de nulo. Make field 'required' - Make field 'required' + Torne o campo 'obrigatório' (required) {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Tornar método assíncrono Make method async (stay void) - Make method async (stay void) + Tornar o método assíncrono (permanecer nulo) Make property 'required' - Make property 'required' + Tornar a propriedade 'obrigatória' (required) {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Alterar 'ref struct' {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Remover palavra-chave 'in' {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Remover modificador 'novo' @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Remover função não utilizada @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Atualizar todos os projetos C# para a versão de linguagem '{0}' Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Atualizar este projeto para versão de linguagem C# '{0}' Use '{0}' - Use '{0}' + Usar '{0}' diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf index b3c2ad03a11fe..e60472fef651e 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Добавить скобки @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Разрешить небезопасный код в этом проекте Assign 'out' parameters - Assign 'out' parameters + Присвоение значений параметров "out" {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + Присвоение значений параметров "out" (при запуске) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Преобразовать в positional record {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + Сделать {0} задачей возврата вместо void. Make field 'required' - Make field 'required' + Сделать поле "required" {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + Преобразовать метод в асинхронный Make method async (stay void) - Make method async (stay void) + Сделать метод асинхронным (оставить void) Make property 'required' - Make property 'required' + Сделать свойство "required" {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + Сделать ref struct {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + Удалить ключевое слово "in" {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + Удалить модификатор "new" @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Удалить неиспользуемую функцию @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Обновить все проекты C# до версии языка "{0}" Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Обновить этот проект C# до версии языка "{0}" Use '{0}' - Use '{0}' + Использовать "{0}" diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf index 8096f21d24f2c..7c51321cc0f3d 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + Parantez ekle @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + Bu projede güvenli olmayan koda izin ver Assign 'out' parameters - Assign 'out' parameters + 'out' parametreleri ata {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + 'out' parametreleri ata (başlangıçta) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + Konum record’una dönüştür {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,7 +94,7 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + {0} öğesi boşluk yerine Görev döndürsün. @@ -104,12 +104,12 @@ Make method async - Make method async + Metodu asenkron yap Make method async (stay void) - Make method async (stay void) + Metodu zaman uyumsuz yap (void olarak bırak) @@ -119,7 +119,7 @@ Make 'ref struct' - Make 'ref struct' + 'ref struct' yap {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + 'in' anahtar sözcüğünü kaldır {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + 'New' değiştiricisini kaldır @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + Kullanılmayan işlevi kaldır @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + Tüm C# projelerini '{0}' dil sürümüne yükselt Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + Bu projeyi C# '{0}' dil sürümüne yükselt Use '{0}' - Use '{0}' + '{0}' kullan diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf index 6f70a68642fdb..e64d86b711b7e 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + 添加括号 @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + 允许在此项目中使用不安全代码 Assign 'out' parameters - Assign 'out' parameters + 为 "out" 参数赋值 {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + 为 "out" 赋值 (在开始处) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + 转换为位置 record {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + 使 {0} 返回 Task,而不是 void。 Make field 'required' - Make field 'required' + 使字段为 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + 使方法异步 Make method async (stay void) - Make method async (stay void) + 使方法异步(保持 void) Make property 'required' - Make property 'required' + 创建 'required' 属性 {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + 生成 "ref struct" {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + 删除 "in" 关键字 {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + 删除 "new" 修饰符 @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + 删除未使用的函数 @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + 将所有 C# 项目升级为语言版本“{0}” Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + 将该项目升级为 C# 语言版本“{0}” Use '{0}' - Use '{0}' + 使用 "{0}" diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf index 4722a099e9529..da202f46d95d4 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf @@ -14,7 +14,7 @@ Add parentheses - Add parentheses + 新增括弧 @@ -24,17 +24,17 @@ Allow unsafe code in this project - Allow unsafe code in this project + 在此專案中允許不安全的程式碼 Assign 'out' parameters - Assign 'out' parameters + 指派 'out' 參數 {Locked="out"} "out" is a C# keyword and should not be localized. Assign 'out' parameters (at start) - Assign 'out' parameters (at start) + 指派 'out' 參數 (開始時) {Locked="out"} "out" is a C# keyword and should not be localized. @@ -54,7 +54,7 @@ Convert to positional record - Convert to positional record + 轉換為位置 record {Locked="record"} "record" is a C# keyword and should not be localized. @@ -94,32 +94,32 @@ Make {0} return Task instead of void. - Make {0} return Task instead of void. + 使 {0} 傳回 Task 而不是 void。 Make field 'required' - Make field 'required' + 將欄位設為 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make method async - Make method async + 讓方法非同步 Make method async (stay void) - Make method async (stay void) + 讓方法不同步 (仍為 void) Make property 'required' - Make property 'required' + 將屬性設為 'required' {Locked="required"} "required" is a C# keyword and should not be localized. Make 'ref struct' - Make 'ref struct' + 設為 'ref struct' {Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized. @@ -149,12 +149,12 @@ Remove 'in' keyword - Remove 'in' keyword + 移除 'in' 關鍵字 {Locked="in"} "in" is a C# keyword and should not be localized. Remove 'new' modifier - Remove 'new' modifier + 移除 'new' 修飾詞 @@ -164,7 +164,7 @@ Remove unused function - Remove unused function + 移除未使用的函式 @@ -179,17 +179,17 @@ Upgrade all C# projects to language version '{0}' - Upgrade all C# projects to language version '{0}' + 將所有 C# 專案升級為語言版本 '{0}' Upgrade this project to C# language version '{0}' - Upgrade this project to C# language version '{0}' + 將此專案升級為 C# 語言版本 '{0}' Use '{0}' - Use '{0}' + 使用 '{0}' diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.cs.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.cs.xlf index 6620c9f9b1ccb..058eeafe0b104 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.cs.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.cs.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Přidat název členu Add missing param nodes - Add missing param nodes + Přidat chybějící uzly parametrů Add parameter to '{0}' - Add parameter to '{0}' + Přidat parametr do {0} Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Přidat parametr do {0} (a přepsání/implementace) Add to '{0}' - Add to '{0}' + Přidat do {0} @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Nastavit metodu jako synchronní @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Podpisy souvisejících metod nalezené v metadatech se nebudou aktualizovat. Remove 'async' modifier - Remove 'async' modifier + Odebrat modifikátor async @@ -114,7 +114,7 @@ Remove tag - Remove tag + Odebrat značku @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Vzít {0} Take both - Take both + Vzít obojí Take bottom - Take bottom + Vzít dolní Take top - Take top + Vzít horní diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.de.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.de.xlf index bbfe901d6a5c0..a2b9a02619c19 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.de.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.de.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Membername hinzufügen Add missing param nodes - Add missing param nodes + Fehlende Parameterknoten hinzufügen Add parameter to '{0}' - Add parameter to '{0}' + Parameter zu "{0}" hinzufügen Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Parameter zu "{0}" (und Außerkraftsetzungen/Implementierungen) hinzufügen Add to '{0}' - Add to '{0}' + Zu "{0}" hinzufügen @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Methode synchron ausführen @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + In Metadaten gefundene ähnliche Methodensignaturen werden nicht aktualisiert. Remove 'async' modifier - Remove 'async' modifier + async-Modifizierer entfernen @@ -114,7 +114,7 @@ Remove tag - Remove tag + Tag entfernen @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + "{0}" übernehmen Take both - Take both + Beide übernehmen Take bottom - Take bottom + Unten übernehmen Take top - Take top + Oben übernehmen diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.es.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.es.xlf index c24ed9fadf968..2f70099a4040e 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.es.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.es.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Agregar nombre de miembro Add missing param nodes - Add missing param nodes + Agregar nodos de parámetros que faltan Add parameter to '{0}' - Add parameter to '{0}' + Agregar parámetro a "{0}" Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Agregar un parámetro a “{0}” (y reemplazos/implementaciones) Add to '{0}' - Add to '{0}' + Agregar a “{0}” @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Convertir el método en sincrónico @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Las signaturas de método relacionadas encontradas en los metadatos no se actualizarán. Remove 'async' modifier - Remove 'async' modifier + Quitar el modificador "async" @@ -114,7 +114,7 @@ Remove tag - Remove tag + Quitar etiqueta @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Tomar "{0}" Take both - Take both + Tomar ambas Take bottom - Take bottom + Tomar parte inferior Take top - Take top + Tomar parte superior diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.fr.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.fr.xlf index 0738acf04a2bb..12475a89d88a1 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.fr.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.fr.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Ajouter le nom du membre Add missing param nodes - Add missing param nodes + Ajouter les nœuds de paramètre manquants Add parameter to '{0}' - Add parameter to '{0}' + Ajouter un paramètre à '{0}' Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Ajouter un paramètre à '{0}' (et aux remplacements/implémentations) Add to '{0}' - Add to '{0}' + Ajouter à '{0}' @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Rendre la méthode synchrone @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Les signatures de méthode associées dans les métadonnées ne sont pas mises à jour. Remove 'async' modifier - Remove 'async' modifier + Supprimer le modificateur 'async' @@ -114,7 +114,7 @@ Remove tag - Remove tag + Supprimer une étiquette @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Prendre '{0}' Take both - Take both + Prendre les deux Take bottom - Take bottom + Prendre le bas Take top - Take top + Prendre le haut diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.it.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.it.xlf index ce288a92f8c2f..95212d711a09c 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.it.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.it.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Aggiungi nome del membro Add missing param nodes - Add missing param nodes + Aggiungi nodi di parametro mancanti Add parameter to '{0}' - Add parameter to '{0}' + Aggiungi il parametro a '{0}' Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Aggiungi il parametro a '{0}' (e override/implementazioni) Add to '{0}' - Add to '{0}' + Aggiungi a '{0}' @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Imposta il metodo come sincrono @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Le firme del metodo correlate trovate nei metadati non verranno aggiornate. Remove 'async' modifier - Remove 'async' modifier + Rimuovi il modificatore 'async' @@ -114,7 +114,7 @@ Remove tag - Remove tag + Rimuovi tag @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Accetta '{0}' Take both - Take both + Accetta entrambi Take bottom - Take bottom + Accetta inferiore Take top - Take top + Accetta superiore diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ja.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ja.xlf index d8a4462420caa..d268b7a917493 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ja.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ja.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + メンバー名を追加します Add missing param nodes - Add missing param nodes + 欠落している Param ノードを追加する Add parameter to '{0}' - Add parameter to '{0}' + パラメーターを '{0}' に追加する Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + パラメーターを '{0}' に追加します (オーバーライド/実装も行います) Add to '{0}' - Add to '{0}' + '{0}' に追加します @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + 同期メソッドに変更します @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + メタデータ内に検出される関連するメソッド シグネチャは更新されません。 Remove 'async' modifier - Remove 'async' modifier + 'async' 修飾子を削除してください @@ -114,7 +114,7 @@ Remove tag - Remove tag + タグの削除 @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + '{0}' を取る Take both - Take both + 両方を取る Take bottom - Take bottom + 下端を取る Take top - Take top + 上端を取る diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ko.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ko.xlf index 17e7dc6d3145c..47598a3e31ab0 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ko.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ko.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + 멤버 이름 추가 Add missing param nodes - Add missing param nodes + 누락된 매개 변수 노드 추가 Add parameter to '{0}' - Add parameter to '{0}' + '{0}'에 매개 변수 추가 Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + '{0}'(및 재정의/구현)에 매개 변수 추가 Add to '{0}' - Add to '{0}' + '{0}'에 추가 @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + 메서드를 동기 메서드로 설정 @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + 메타데이터에서 찾은 관련 메서드 시그니처가 업데이트되지 않습니다. Remove 'async' modifier - Remove 'async' modifier + 'async' 한정자 제거 @@ -114,7 +114,7 @@ Remove tag - Remove tag + 태그 제거 @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + '{0}' 사용 Take both - Take both + 둘 다 사용 Take bottom - Take bottom + 맨 아래 사용 Take top - Take top + 맨 위 사용 diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pl.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pl.xlf index 1a79682d4d1e3..5176ccfedfead 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pl.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pl.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Dodaj nazwę składowej Add missing param nodes - Add missing param nodes + Dodaj brakujące węzły parametrów Add parameter to '{0}' - Add parameter to '{0}' + Dodaj parametr do elementu „{0}” Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Dodaj parametr do elementu „{0}” (oraz przesłonięć/implementacji) Add to '{0}' - Add to '{0}' + Dodaj do elementu „{0}” @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Ustaw metodę jako synchroniczną @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Sygnatury powiązanych metod znalezione w metadanych nie zostaną zaktualizowane. Remove 'async' modifier - Remove 'async' modifier + Usuń modyfikator „async” @@ -114,7 +114,7 @@ Remove tag - Remove tag + Usuń tag @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Przyjmij „{0}” Take both - Take both + Przyjmij oba Take bottom - Take bottom + Przyjmij dół Take top - Take top + Przyjmij górę diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pt-BR.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pt-BR.xlf index 139531593c53a..e8a6983c586e0 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pt-BR.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.pt-BR.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Adicionar o nome do membro Add missing param nodes - Add missing param nodes + Adicionar nós de parâmetro ausentes Add parameter to '{0}' - Add parameter to '{0}' + Adicionar parâmetro ao '{0}' Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Adicionar parâmetro ao '{0}' (e substituições/implementações) Add to '{0}' - Add to '{0}' + Adicionar para '{0}' @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Tornar o método síncrono @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + As assinaturas de método relacionadas encontradas nos metadados não serão atualizadas. Remove 'async' modifier - Remove 'async' modifier + Remover o modificador 'async' @@ -114,7 +114,7 @@ Remove tag - Remove tag + Remover tag @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Obter '{0}' Take both - Take both + Obter ambos Take bottom - Take bottom + Obter inferior Take top - Take top + Obter superior diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ru.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ru.xlf index eb7e41f351bad..4ba748f8729a1 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ru.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.ru.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Добавить имя элемента Add missing param nodes - Add missing param nodes + Добавить отсутствующие узлы параметров Add parameter to '{0}' - Add parameter to '{0}' + Добавить параметр в "{0}" Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + Добавить параметр в "{0}" (а также переопределения или реализации) Add to '{0}' - Add to '{0}' + Добавить в "{0}" @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Преобразовать метод в синхронный @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Связанные сигнатуры методов, найденные в метаданных, не будут обновлены. Remove 'async' modifier - Remove 'async' modifier + Удалить модификатор "async" @@ -114,7 +114,7 @@ Remove tag - Remove tag + Удалить тег @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + Принимать "{0}" Take both - Take both + Принимать оба Take bottom - Take bottom + Принимать нижнее Take top - Take top + Принимать верхнее diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.tr.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.tr.xlf index 04dd6ac3f5b64..df84fc9392049 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.tr.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.tr.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + Üye adı Ekle Add missing param nodes - Add missing param nodes + Eksik parametre düğümlerini ekle Add parameter to '{0}' - Add parameter to '{0}' + '{0}' öğesine parametre ekle Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + '{0}' öğesine (ve geçersiz kılmalara/uygulamalara) parametre ekle Add to '{0}' - Add to '{0}' + '{0}' öğesine ekle @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + Metodu zaman uyumlu hale getir @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + Meta verilerde bulunan ilgili metot imzaları güncelleştirilmez. Remove 'async' modifier - Remove 'async' modifier + 'async' değiştiricisini kaldırın @@ -114,7 +114,7 @@ Remove tag - Remove tag + Etiketi Kaldır @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + '{0}' al Take both - Take both + Her ikisini de al Take bottom - Take bottom + Alttakini al Take top - Take top + Üsttekini al diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hans.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hans.xlf index cc2b5efb2f959..45be72433623e 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hans.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hans.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + 添加成员名称 Add missing param nodes - Add missing param nodes + 添加缺少的参数节点 Add parameter to '{0}' - Add parameter to '{0}' + 将参数添加到“{0}” Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + 将参数添加到“{0}”(和重写/实现) Add to '{0}' - Add to '{0}' + 添加到“{0}” @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + 使方法同步 @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + 不更新在元数据中发现的相关方法签名。 Remove 'async' modifier - Remove 'async' modifier + 删除 "async" 修饰符 @@ -114,7 +114,7 @@ Remove tag - Remove tag + 删除标记 @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + 采用“{0}” Take both - Take both + 二者均采用 Take bottom - Take bottom + 采用底值 Take top - Take top + 采用顶值 diff --git a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hant.xlf b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hant.xlf index 89b1ec0a7caa9..85ac1034dd3df 100644 --- a/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hant.xlf +++ b/src/Analyzers/Core/CodeFixes/xlf/CodeFixesResources.zh-Hant.xlf @@ -29,27 +29,27 @@ Add member name - Add member name + 新增成員名稱 Add missing param nodes - Add missing param nodes + 新增遺失的參數節點 Add parameter to '{0}' - Add parameter to '{0}' + 將參數新增至 '{0}' Add parameter to '{0}' (and overrides/implementations) - Add parameter to '{0}' (and overrides/implementations) + 將參數新增至 '{0}' (以及覆寫/執行) Add to '{0}' - Add to '{0}' + 新增至 '{0}' @@ -84,7 +84,7 @@ Make method synchronous - Make method synchronous + 讓方法同步 @@ -94,12 +94,12 @@ Related method signatures found in metadata will not be updated. - Related method signatures found in metadata will not be updated. + 將不會更新中繼資料中所找到的相關方法簽章。 Remove 'async' modifier - Remove 'async' modifier + 移除 'async' 修飾元 @@ -114,7 +114,7 @@ Remove tag - Remove tag + 移除標記 @@ -124,22 +124,22 @@ Take '{0}' - Take '{0}' + 接受 '{0}' Take both - Take both + 接受兩者 Take bottom - Take bottom + 接受底端 Take top - Take top + 接受頂端 diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf index 9aa93edf41ada..0d5cbbb5df0bd 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Převeď {0} na asynchronní funkci Async. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Převést na asynchronní funkci Make Async Sub - Make Async Sub + Převést na asynchronní proceduru Sub diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.de.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.de.xlf index e56ce3964e4e6..350532a7b1dcb 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.de.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.de.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + "{0}" in eine Async-Funktion umwandeln. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Funktion als asynchron definieren Make Async Sub - Make Async Sub + Sub als asynchron definieren diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.es.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.es.xlf index 4abe3c24658f8..5d6c8bbb31e9b 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.es.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.es.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Convertir {0} en una función Async. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Convertir función en asincrónica Make Async Sub - Make Async Sub + Convertir Sub en asincrónico diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf index 9405d9fc87f57..af93387335431 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Faire de {0} une fonction Async. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Rendre la fonction asynchrone Make Async Sub - Make Async Sub + Rendre le Sub asynchrone diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.it.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.it.xlf index 39df8c314fd3d..33f106be653d7 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.it.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.it.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Trasformare {0} in una funzione asincrona. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Rendi asincrona la funzione Make Async Sub - Make Async Sub + Rendi asincrona la funzione sub diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf index 130e2c138a070..697246d999af1 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + {0} を Async Function にします。 @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Async Function を作成する Make Async Sub - Make Async Sub + Async Sub にする diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ko.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ko.xlf index 2381055caf3b1..a760d8d7a8e2d 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ko.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ko.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + {0}을(를) 비동기 함수로 설정합니다. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + 비동기 함수로 설정 Make Async Sub - Make Async Sub + 비동기 Sub로 설정 diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf index 06a1dad4933e3..71b51eb7cefb1 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Ustaw funkcję {0} jako funkcję asynchroniczną. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Ustaw funkcję jako asynchroniczną Make Async Sub - Make Async Sub + Ustaw podprocedurę jako asynchroniczną diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf index b51735e7f5765..2e54e94d736fa 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Tornar {0} uma Função Assíncrona. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Tornar a função assíncrona Make Async Sub - Make Async Sub + Tornar Sub Assíncrona diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ru.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ru.xlf index 0394febb03a1f..068e4809b9f54 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ru.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ru.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + Сделать {0} асинхронной функцией. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Сделать функцию асинхронной Make Async Sub - Make Async Sub + Сделать Sub асинхронной diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf index 4e5c9acce1031..d6fd39b786523 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + {0} öğesini bir Zaman Uyumsuz İşlev yap. @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + Zaman Uyumsuz İşlev Yap Make Async Sub - Make Async Sub + Zaman Uyumsuz Alt Yap diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hans.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hans.xlf index b9a061a7824e3..b1dd33acf3a8a 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hans.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hans.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + 使 {0} 为异步函数。 @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + 使成为异步函数 Make Async Sub - Make Async Sub + 使成为异步 Sub diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf index e354b055e5266..58f7ae681afbd 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf @@ -24,7 +24,7 @@ Make {0} an Async Function. - Make {0} an Async Function. + 讓 {0} 成為非同步函式。 @@ -34,12 +34,12 @@ Make Async Function - Make Async Function + 讓非同步函式 Make Async Sub - Make Async Sub + 轉換為非同步 Sub diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index d60f63528ee98..9e4e502e2aec7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -1708,7 +1708,17 @@ internal partial class RefSafetyAnalysis uint scopeOfTheContainingExpression) { var data = expression.GetInterpolatedStringHandlerData(); +#if DEBUG + // VisitArgumentsAndGetArgumentPlaceholders() does not visit data.Construction + // since that expression does not introduce locals or placeholders that are needed + // by GetValEscape() or CheckValEscape(), so we disable tracking here. + var previousVisited = _visited; + _visited = null; +#endif uint escapeScope = GetValEscape(data.Construction, scopeOfTheContainingExpression); +#if DEBUG + _visited = previousVisited; +#endif var arguments = ArrayBuilder.GetInstance(); GetInterpolatedStringHandlerArgumentsForEscape(expression, arguments); @@ -2084,6 +2094,9 @@ bool isRefEscape _compilation.IsPeVerifyCompatEnabled, stackLocalsOpt: null)) { +#if DEBUG + AssertVisited(receiver); +#endif // Equivalent to a non-ref local with the underlying receiver as an initializer provided at declaration receiver = new BoundCapturedReceiverPlaceholder(receiver.Syntax, receiver, _localScopeDepth, receiver.Type).MakeCompilerGenerated(); } @@ -2910,6 +2923,10 @@ internal void ValidateEscape(BoundExpression expr, uint escapeTo, bool isByRef, /// internal uint GetRefEscape(BoundExpression expr, uint scopeOfTheContainingExpression) { +#if DEBUG + AssertVisited(expr); +#endif + // cannot infer anything from errors if (expr.HasAnyErrors) { @@ -3146,6 +3163,10 @@ internal uint GetRefEscape(BoundExpression expr, uint scopeOfTheContainingExpres /// internal bool CheckRefEscape(SyntaxNode node, BoundExpression expr, uint escapeFrom, uint escapeTo, bool checkingReceiver, BindingDiagnosticBag diagnostics) { +#if DEBUG + AssertVisited(expr); +#endif + Debug.Assert(!checkingReceiver || expr.Type.IsValueType || expr.Type.IsTypeParameter()); if (escapeTo >= escapeFrom) @@ -3468,6 +3489,10 @@ internal uint GetBroadestValEscape(BoundTupleExpression expr, uint scopeOfTheCon /// internal uint GetValEscape(BoundExpression expr, uint scopeOfTheContainingExpression) { +#if DEBUG + AssertVisited(expr); +#endif + // cannot infer anything from errors if (expr.HasAnyErrors) { @@ -3867,6 +3892,10 @@ private uint GetValEscape(ImmutableArray expressions, uint scop /// internal bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint escapeFrom, uint escapeTo, bool checkingReceiver, BindingDiagnosticBag diagnostics) { +#if DEBUG + AssertVisited(expr); +#endif + Debug.Assert(!checkingReceiver || expr.Type.IsValueType || expr.Type.IsTypeParameter()); if (escapeTo >= escapeFrom) @@ -4486,7 +4515,17 @@ private bool CheckInterpolatedStringHandlerConversionEscape(BoundExpression expr // and then on a subsequent call it either assigns that saved value to another ref struct with a larger // escape, or does the opposite. In either case, we need to check. +#if DEBUG + // VisitArgumentsAndGetArgumentPlaceholders() does not visit data.Construction + // since that expression does not introduce locals or placeholders that are needed + // by GetValEscape() or CheckValEscape(), so we disable tracking here. + var previousVisited = _visited; + _visited = null; +#endif CheckValEscape(expression.Syntax, data.Construction, escapeFrom, escapeTo, checkingReceiver: false, diagnostics); +#if DEBUG + _visited = previousVisited; +#endif var arguments = ArrayBuilder.GetInstance(); GetInterpolatedStringHandlerArgumentsForEscape(expression, arguments); diff --git a/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs b/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs index 4fdddcadadd61..df7479226f64c 100644 --- a/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs @@ -2,9 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; @@ -82,6 +84,10 @@ private static bool InUnsafeMethod(Symbol symbol) private Dictionary? _localEscapeScopes; private Dictionary? _placeholderScopes; private uint _patternInputValEscape; +#if DEBUG + private const int MaxTrackVisited = 100; // Avoid tracking if too many expressions. + private HashSet? _visited = new HashSet(); +#endif private RefSafetyAnalysis( CSharpCompilation compilation, @@ -208,8 +214,13 @@ private void SetLocalScopes(LocalSymbol local, uint refEscapeScope, uint valEsca private void AddPlaceholderScope(BoundValuePlaceholderBase placeholder, uint valEscapeScope) { + Debug.Assert(_placeholderScopes?.ContainsKey(placeholder) != true); + + // Consider not adding the placeholder to the dictionary if the escape scope is + // CallingMethod, and simply fallback to that value in GetPlaceholderScope(). + _placeholderScopes ??= new Dictionary(); - _placeholderScopes.Add(placeholder, valEscapeScope); + _placeholderScopes[placeholder] = valEscapeScope; } #pragma warning disable IDE0060 @@ -225,14 +236,39 @@ private void RemovePlaceholderScope(BoundValuePlaceholderBase placeholder) private uint GetPlaceholderScope(BoundValuePlaceholderBase placeholder) { - // https://github.com/dotnet/roslyn/issues/67070: Assert should be re-enabled when placeholders are included. - //Debug.Assert(_placeholderScopes?.ContainsKey(placeholder) == true); + Debug.Assert(_placeholderScopes?.ContainsKey(placeholder) == true); return _placeholderScopes?.TryGetValue(placeholder, out var scope) == true ? scope : CallingMethodScope; } +#if DEBUG + private bool ContainsPlaceholderScope(BoundValuePlaceholderBase placeholder) + { + if (_placeholderScopes?.ContainsKey(placeholder) == true) + { + return true; + } + + // _placeholderScopes should contain all placeholders that may be used by GetValEscape() or CheckValEscape(). + // The following placeholders are not needed by those methods and can be ignored, however. + switch (placeholder) + { + case BoundObjectOrCollectionValuePlaceholder: + return true; // CheckValEscapeOfObjectInitializer() does not use BoundObjectOrCollectionValuePlaceholder. + case BoundInterpolatedStringHandlerPlaceholder: + return true; // CheckInterpolatedStringHandlerConversionEscape() does not use BoundInterpolatedStringHandlerPlaceholder. + case BoundImplicitIndexerValuePlaceholder: + return placeholder.Type?.SpecialType == SpecialType.System_Int32; + case BoundCapturedReceiverPlaceholder: + return true; // BoundCapturedReceiverPlaceholder is created in GetInvocationArgumentsForEscape(), and was not part of the BoundNode tree. + default: + return false; + } + } +#endif + public override BoundNode? VisitBlock(BoundBlock node) { using var _1 = new UnsafeRegion(this, _inUnsafeRegion || node.HasUnsafeModifier); @@ -243,17 +279,36 @@ private uint GetPlaceholderScope(BoundValuePlaceholderBase placeholder) public override BoundNode? Visit(BoundNode? node) { #if DEBUG - if (node is BoundValuePlaceholderBase placeholder - // CheckValEscapeOfObjectInitializer() does not use BoundObjectOrCollectionValuePlaceholder. - // CheckInterpolatedStringHandlerConversionEscape() does not use BoundInterpolatedStringHandlerPlaceholder. - && node is not (BoundObjectOrCollectionValuePlaceholder or BoundInterpolatedStringHandlerPlaceholder)) + if (node is BoundValuePlaceholderBase placeholder) { - Debug.Assert(_placeholderScopes?.ContainsKey(placeholder) == true); + Debug.Assert(ContainsPlaceholderScope(placeholder)); + } + else if (node is BoundExpression expr) + { + if (_visited is { } && _visited.Count <= MaxTrackVisited) + { + bool added = _visited.Add(expr); + Debug.Assert(added); + } } #endif return base.Visit(node); } +#if DEBUG + private void AssertVisited(BoundExpression expr) + { + if (expr is BoundValuePlaceholderBase placeholder) + { + Debug.Assert(ContainsPlaceholderScope(placeholder)); + } + else if (_visited is { } && _visited.Count <= MaxTrackVisited) + { + Debug.Assert(_visited.Contains(expr)); + } + } +#endif + private void VisitFieldOrPropertyInitializer(BoundInitializer initializer) { var fieldEqualsValue = (BoundFieldEqualsValue)initializer; @@ -262,7 +317,7 @@ private void VisitFieldOrPropertyInitializer(BoundInitializer initializer) using var _ = new LocalScope(this, fieldEqualsValue.Locals); - base.Visit(value); + Visit(value); ValidateEscape(value, CallingMethodScope, isByRef: field.RefKind != RefKind.None, _diagnostics); } @@ -307,6 +362,9 @@ private void VisitFieldOrPropertyInitializer(BoundInitializer initializer) { using var _ = new LocalScope(this, node.Locals); + this.Visit(node.DeclarationsOpt); + this.Visit(node.ExpressionOpt); + var placeholders = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); if (node.AwaitOpt is { } awaitableInfo) { @@ -317,7 +375,9 @@ private void VisitFieldOrPropertyInitializer(BoundInitializer initializer) } using var region = new PlaceholderRegion(this, placeholders); - return base.VisitUsingStatement(node); + this.Visit(node.AwaitOpt); + this.Visit(node.Body); + return null; } public override BoundNode? VisitUsingLocalDeclarations(BoundUsingLocalDeclarations node) @@ -352,16 +412,19 @@ private void VisitFieldOrPropertyInitializer(BoundInitializer initializer) public override BoundNode? VisitSwitchStatement(BoundSwitchStatement node) { + this.Visit(node.Expression); using var _1 = new LocalScope(this, node.InnerLocals); using var _2 = new PatternInput(this, GetValEscape(node.Expression, _localScopeDepth)); - base.VisitSwitchStatement(node); + this.VisitList(node.SwitchSections); + this.Visit(node.DefaultLabel); return null; } public override BoundNode? VisitConvertedSwitchExpression(BoundConvertedSwitchExpression node) { + this.Visit(node.Expression); using var _ = new PatternInput(this, GetValEscape(node.Expression, _localScopeDepth)); - base.VisitConvertedSwitchExpression(node); + this.VisitList(node.SwitchArms); return null; } @@ -507,8 +570,10 @@ private void RemoveLocalScopes(LocalSymbol local) public override BoundNode? VisitIsPatternExpression(BoundIsPatternExpression node) { + this.Visit(node.Expression); using var _ = new PatternInput(this, GetValEscape(node.Expression, _localScopeDepth)); - return base.VisitIsPatternExpression(node); + this.Visit(node.Pattern); + return null; } public override BoundNode? VisitDeclarationPattern(BoundDeclarationPattern node) @@ -580,24 +645,27 @@ private void SetPatternLocalScopes(BoundObjectPattern pattern) return null; } - private PlaceholderRegion GetArgumentPlaceholders(BoundExpression? receiverOpt, ImmutableArray arguments) + private void VisitArgumentsAndGetArgumentPlaceholders(BoundExpression? receiverOpt, ImmutableArray arguments) { - var placeholders = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); - foreach (var arg in arguments) + Visit(receiverOpt); + + for (int i = 0; i < arguments.Length; i++) { + var arg = arguments[i]; if (arg is BoundConversion { ConversionKind: ConversionKind.InterpolatedStringHandler, Operand: BoundInterpolatedString or BoundBinaryOperator } conversion) { var interpolationData = conversion.Operand.GetInterpolatedStringHandlerData(); - GetInterpolatedStringPlaceholders(placeholders, interpolationData, receiverOpt, arguments); + var placeholders = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); + GetInterpolatedStringPlaceholders(placeholders, interpolationData, receiverOpt, i, arguments); + _ = new PlaceholderRegion(this, placeholders); } + Visit(arg); } - return new PlaceholderRegion(this, placeholders); } public override BoundNode? VisitCall(BoundCall node) { - using var _ = GetArgumentPlaceholders(node.ReceiverOpt, node.Arguments); - base.VisitCall(node); + VisitArgumentsAndGetArgumentPlaceholders(node.ReceiverOpt, node.Arguments); if (!node.HasErrors) { @@ -621,6 +689,7 @@ private PlaceholderRegion GetArgumentPlaceholders(BoundExpression? receiverOpt, ArrayBuilder<(BoundValuePlaceholderBase, uint)> placeholders, in InterpolatedStringHandlerData interpolationData, BoundExpression? receiver, + int nArgumentsVisited, ImmutableArray arguments) { placeholders.Add((interpolationData.ReceiverPlaceholder, _localScopeDepth)); @@ -633,13 +702,32 @@ private PlaceholderRegion GetArgumentPlaceholders(BoundExpression? receiverOpt, { case BoundInterpolatedStringArgumentPlaceholder.InstanceParameter: Debug.Assert(receiver != null); - valEscapeScope = receiver.GetRefKind().IsWritableReference() ? GetRefEscape(receiver, _localScopeDepth) : GetValEscape(receiver, _localScopeDepth); + if (receiver is null) + { + valEscapeScope = CallingMethodScope; + } + else + { + valEscapeScope = receiver.GetRefKind().IsWritableReference() ? GetRefEscape(receiver, _localScopeDepth) : GetValEscape(receiver, _localScopeDepth); + } break; case BoundInterpolatedStringArgumentPlaceholder.TrailingConstructorValidityParameter: + Debug.Assert(placeholder.Type.SpecialType == SpecialType.System_Boolean); + // Escape scope of bool parameter is CallingMethod, which is the default for placeholders. + continue; case BoundInterpolatedStringArgumentPlaceholder.UnspecifiedParameter: + // Error condition, no need for additional ref safety errors. continue; case >= 0: - valEscapeScope = GetValEscape(arguments[argIndex], _localScopeDepth); + if (argIndex < nArgumentsVisited) + { + valEscapeScope = GetValEscape(arguments[argIndex], _localScopeDepth); + } + else + { + // Error condition, see ERR_InterpolatedStringHandlerArgumentLocatedAfterInterpolatedString. + valEscapeScope = CallingMethodScope; // Consider skipping this placeholder entirely since CallingMethodScope is the fallback in GetPlaceholderScope(). + } break; default: throw ExceptionUtilities.UnexpectedValue(placeholder.ArgumentIndex); @@ -650,31 +738,55 @@ private PlaceholderRegion GetArgumentPlaceholders(BoundExpression? receiverOpt, public override BoundNode? VisitObjectCreationExpression(BoundObjectCreationExpression node) { - using var _ = GetArgumentPlaceholders(receiverOpt: null, node.Arguments); - base.VisitObjectCreationExpression(node); + VisitObjectCreationExpressionBase(node); + return null; + } + + public override BoundNode? VisitDynamicObjectCreationExpression(BoundDynamicObjectCreationExpression node) + { + VisitObjectCreationExpressionBase(node); + return null; + } + + public override BoundNode? VisitNewT(BoundNewT node) + { + VisitObjectCreationExpressionBase(node); + return null; + } + + public override BoundNode? VisitNoPiaObjectCreationExpression(BoundNoPiaObjectCreationExpression node) + { + VisitObjectCreationExpressionBase(node); + return null; + } + + private void VisitObjectCreationExpressionBase(BoundObjectCreationExpressionBase node) + { + VisitArgumentsAndGetArgumentPlaceholders(receiverOpt: null, node.Arguments); + Visit(node.InitializerExpressionOpt); if (!node.HasErrors) { var constructor = node.Constructor; - CheckInvocationArgMixing( - node.Syntax, - constructor, - receiverOpt: null, - constructor.Parameters, - node.Arguments, - node.ArgumentRefKindsOpt, - node.ArgsToParamsOpt, - _localScopeDepth, - _diagnostics); + if (constructor is { }) + { + CheckInvocationArgMixing( + node.Syntax, + constructor, + receiverOpt: null, + constructor.Parameters, + node.Arguments, + node.ArgumentRefKindsOpt, + node.ArgsToParamsOpt, + _localScopeDepth, + _diagnostics); + } } - - return null; } public override BoundNode? VisitIndexerAccess(BoundIndexerAccess node) { - using var _ = GetArgumentPlaceholders(node.ReceiverOpt, node.Arguments); - base.VisitIndexerAccess(node); + VisitArgumentsAndGetArgumentPlaceholders(node.ReceiverOpt, node.Arguments); if (!node.HasErrors) { @@ -696,8 +808,7 @@ private PlaceholderRegion GetArgumentPlaceholders(BoundExpression? receiverOpt, public override BoundNode? VisitFunctionPointerInvocation(BoundFunctionPointerInvocation node) { - using var _ = GetArgumentPlaceholders(receiverOpt: null, node.Arguments); - base.VisitFunctionPointerInvocation(node); + VisitArgumentsAndGetArgumentPlaceholders(receiverOpt: null, node.Arguments); if (!node.HasErrors) { @@ -719,10 +830,11 @@ private PlaceholderRegion GetArgumentPlaceholders(BoundExpression? receiverOpt, public override BoundNode? VisitAwaitExpression(BoundAwaitExpression node) { + this.Visit(node.Expression); var placeholders = ArrayBuilder<(BoundValuePlaceholderBase, uint)>.GetInstance(); GetAwaitableInstancePlaceholders(placeholders, node.AwaitableInfo, GetValEscape(node.Expression, _localScopeDepth)); using var _ = new PlaceholderRegion(this, placeholders); - base.VisitAwaitExpression(node); + this.Visit(node.AwaitableInfo); return null; } @@ -734,6 +846,15 @@ private void GetAwaitableInstancePlaceholders(ArrayBuilder<(BoundValuePlaceholde } } + public override BoundNode? VisitImplicitIndexerAccess(BoundImplicitIndexerAccess node) + { + // Verify we're only skipping placeholders for int values, where the escape scope is always CallingMethod. + Debug.Assert(node.ArgumentPlaceholders.All(p => p is BoundImplicitIndexerValuePlaceholder { Type.SpecialType: SpecialType.System_Int32 })); + + base.VisitImplicitIndexerAccess(node); + return null; + } + // Based on NullableWalker.VisitDeconstructionAssignmentOperator(). public override BoundNode? VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node) { @@ -869,6 +990,7 @@ private static ImmutableArray GetDeconstructionRightParts(Bound public override BoundNode? VisitForEachStatement(BoundForEachStatement node) { + this.Visit(node.Expression); uint collectionEscape = GetValEscape(node.Expression, _localScopeDepth); using var _ = new LocalScope(this, ImmutableArray.Empty); @@ -888,7 +1010,11 @@ private static ImmutableArray GetDeconstructionRightParts(Bound } using var region = new PlaceholderRegion(this, placeholders); - base.VisitForEachStatement(node); + this.Visit(node.IterationVariableType); + this.Visit(node.IterationErrorExpressionOpt); + this.Visit(node.DeconstructionOpt); + this.Visit(node.AwaitOpt); + this.Visit(node.Body); foreach (var local in node.IterationVariables) { diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 8588bac47319b..2ca4150db5114 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -334,7 +334,7 @@ internal SymbolInfo GetCrefSymbolInfo(int position, CrefSyntax crefSyntax, Symbo if (binder?.InCref == true) { ImmutableArray symbols = BindCref(crefSyntax, binder); - return GetCrefSymbolInfo(symbols, options, hasParameterList); + return GetCrefSymbolInfo(OneOrMany.Create(symbols), options, hasParameterList); } return SymbolInfo.None; @@ -362,9 +362,9 @@ internal static bool HasParameterList(CrefSyntax crefSyntax) return false; } - private static SymbolInfo GetCrefSymbolInfo(ImmutableArray symbols, SymbolInfoOptions options, bool hasParameterList) + private static SymbolInfo GetCrefSymbolInfo(OneOrMany symbols, SymbolInfoOptions options, bool hasParameterList) { - switch (symbols.Length) + switch (symbols.Count) { case 0: return SymbolInfo.None; @@ -723,7 +723,7 @@ public SymbolInfo GetSpeculativeSymbolInfo(int position, ExpressionSyntax expres Debug.Assert(boundNode == null || crefSymbols.IsDefault); if (boundNode == null) { - return crefSymbols.IsDefault ? SymbolInfo.None : GetCrefSymbolInfo(crefSymbols, SymbolInfoOptions.DefaultOptions, hasParameterList: false); + return crefSymbols.IsDefault ? SymbolInfo.None : GetCrefSymbolInfo(OneOrMany.Create(crefSymbols), SymbolInfoOptions.DefaultOptions, hasParameterList: false); } var symbolInfo = this.GetSymbolInfoForNode(SymbolInfoOptions.DefaultOptions, boundNode, boundNode, boundNodeForSyntacticParent: null, binderOpt: binder); @@ -1920,7 +1920,7 @@ private bool IsInTypeofExpression(int position) // Get symbols and result kind from the lowest and highest nodes associated with the // syntax node. - ImmutableArray symbols = GetSemanticSymbols( + OneOrMany symbols = GetSemanticSymbols( boundExpr, boundNodeForSyntacticParent, binderOpt, options, out bool isDynamic, out LookupResultKind resultKind, out ImmutableArray unusedMemberGroup); if (highestBoundNode is BoundExpression highestBoundExpr) @@ -1928,10 +1928,10 @@ private bool IsInTypeofExpression(int position) LookupResultKind highestResultKind; bool highestIsDynamic; ImmutableArray unusedHighestMemberGroup; - ImmutableArray highestSymbols = GetSemanticSymbols( + OneOrMany highestSymbols = GetSemanticSymbols( highestBoundExpr, boundNodeForSyntacticParent, binderOpt, options, out highestIsDynamic, out highestResultKind, out unusedHighestMemberGroup); - if ((symbols.Length != 1 || resultKind == LookupResultKind.OverloadResolutionFailure) && highestSymbols.Length > 0) + if ((symbols.Count != 1 || resultKind == LookupResultKind.OverloadResolutionFailure) && highestSymbols.Count > 0) { symbols = highestSymbols; resultKind = highestResultKind; @@ -1973,13 +1973,13 @@ private bool IsInTypeofExpression(int position) { // Caas clients don't want ErrorTypeSymbol in the symbols, but the best guess // instead. If no best guess, then nothing is returned. - var builder = ArrayBuilder.GetInstance(symbols.Length); + var builder = ArrayBuilder.GetInstance(symbols.Count); foreach (Symbol symbol in symbols) { AddUnwrappingErrorTypes(builder, symbol); } - symbols = builder.ToImmutableAndFree(); + symbols = builder.ToOneOrManyAndFree(); } if ((options & SymbolInfoOptions.ResolveAliases) != 0) @@ -1987,7 +1987,7 @@ private bool IsInTypeofExpression(int position) symbols = UnwrapAliases(symbols); } - if (resultKind == LookupResultKind.Viable && symbols.Length > 1) + if (resultKind == LookupResultKind.Viable && symbols.Count > 1) { resultKind = LookupResultKind.OverloadResolutionFailure; } @@ -2319,12 +2319,12 @@ internal static SymbolInfo GetSymbolInfoForSymbol(Symbol symbol, SymbolInfoOptio if ((object)originalErrorSymbol != null) { // Error case. - var symbols = ImmutableArray.Empty; + var symbols = OneOrMany.Empty; LookupResultKind resultKind = originalErrorSymbol.ResultKind; if (resultKind != LookupResultKind.Empty) { - symbols = originalErrorSymbol.CandidateSymbols; + symbols = OneOrMany.Create(originalErrorSymbol.CandidateSymbols); } if ((options & SymbolInfoOptions.ResolveAliases) != 0) @@ -2358,7 +2358,7 @@ protected static Symbol UnwrapAlias(Symbol symbol) return symbol is AliasSymbol aliasSym ? aliasSym.Target : symbol; } - protected static ImmutableArray UnwrapAliases(ImmutableArray symbols) + protected static OneOrMany UnwrapAliases(OneOrMany symbols) { bool anyAliases = false; @@ -2379,7 +2379,7 @@ protected static ImmutableArray UnwrapAliases(ImmutableArray sym AddUnwrappingErrorTypes(builder, UnwrapAlias(symbol)); } - return builder.ToImmutableAndFree(); + return builder.ToOneOrManyAndFree(); } // This is used by other binding APIs to invoke the right binder API @@ -3331,7 +3331,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) // Get the symbols and possible method or property group associated with a bound node, as // they should be exposed through GetSemanticInfo. // NB: It is not safe to pass a null binderOpt during speculative binding. - private ImmutableArray GetSemanticSymbols( + private OneOrMany GetSemanticSymbols( BoundExpression boundNode, BoundNode boundNodeForSyntacticParent, Binder binderOpt, @@ -3341,7 +3341,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) out ImmutableArray memberGroup) { memberGroup = ImmutableArray.Empty; - ImmutableArray symbols = ImmutableArray.Empty; + OneOrMany symbols = OneOrMany.Empty; resultKind = LookupResultKind.Viable; isDynamic = false; @@ -3364,7 +3364,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) { if (resultKind == LookupResultKind.NotCreatable) { - return expr.Symbols; + return OneOrMany.Create(expr.Symbols); } else if (expr.Type.IsDelegateType()) { @@ -3375,7 +3375,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) memberGroup = expr.Symbols; } - return expr.Symbols; + return OneOrMany.Create(expr.Symbols); } case BoundKind.DelegateCreationExpression: @@ -3402,11 +3402,11 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) if ((object)originalErrorType != null) { resultKind = originalErrorType.ResultKind; - symbols = originalErrorType.CandidateSymbols; + symbols = OneOrMany.Create(originalErrorType.CandidateSymbols); } else { - symbols = ImmutableArray.Create(typeSymbol); + symbols = OneOrMany.Create(typeSymbol); } } break; @@ -3448,7 +3448,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) case BoundKind.FunctionPointerInvocation: { var invocation = (BoundFunctionPointerInvocation)boundNode; - symbols = ImmutableArray.Create(invocation.FunctionPointer); + symbols = OneOrMany.Create(invocation.FunctionPointer); resultKind = invocation.ResultKind; break; } @@ -3477,7 +3477,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) resultKind = indexerAccess.ResultKind; ImmutableArray originalIndexersOpt = indexerAccess.OriginalIndexersOpt; - symbols = originalIndexersOpt.IsDefault ? ImmutableArray.Create(indexerAccess.Indexer) : StaticCast.From(originalIndexersOpt); + symbols = originalIndexersOpt.IsDefault ? OneOrMany.Create(indexerAccess.Indexer) : StaticCast.From(OneOrMany.Create(originalIndexersOpt)); } break; @@ -3492,12 +3492,12 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) var methodSymbol = eventAssignment.IsAddition ? eventSymbol.AddMethod : eventSymbol.RemoveMethod; if ((object)methodSymbol == null) { - symbols = ImmutableArray.Empty; + symbols = OneOrMany.Empty; resultKind = LookupResultKind.Empty; } else { - symbols = ImmutableArray.Create(methodSymbol); + symbols = OneOrMany.Create(methodSymbol); resultKind = eventAssignment.ResultKind; } break; @@ -3509,7 +3509,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) // When we're looking at the left-hand side of an event assignment, we synthesize a BoundEventAccess node. This node does not have // nullability information, however, so if we're in that case then we need to grab the event symbol from the parent event assignment // which does have the nullability-reinferred symbol - symbols = ImmutableArray.Create(parentOperator.Event); + symbols = OneOrMany.Create(parentOperator.Event); resultKind = parentOperator.ResultKind; break; @@ -3522,7 +3522,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) { var symbol = conversion.SymbolOpt; Debug.Assert((object)symbol != null); - symbols = ImmutableArray.Create(ReducedExtensionMethodSymbol.Create(symbol)); + symbols = OneOrMany.Create(ReducedExtensionMethodSymbol.Create(symbol)); resultKind = conversion.ResultKind; } else if (conversion.ConversionKind.IsUserDefinedConversion()) @@ -3595,7 +3595,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) } else { - symbols = candidateSymbols; + symbols = OneOrMany.Create(candidateSymbols); break; } } @@ -3611,28 +3611,31 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) if (query.Operation != null && (object)query.Operation.ExpressionSymbol != null) builder.Add(query.Operation.ExpressionSymbol); if ((object)query.DefinedSymbol != null) builder.Add(query.DefinedSymbol); if (query.Cast != null && (object)query.Cast.ExpressionSymbol != null) builder.Add(query.Cast.ExpressionSymbol); - symbols = builder.ToImmutableAndFree(); + symbols = builder.ToOneOrManyAndFree(); } break; case BoundKind.DynamicInvocation: var dynamicInvocation = (BoundDynamicInvocation)boundNode; Debug.Assert(dynamicInvocation.ExpressionSymbol is null); - symbols = memberGroup = dynamicInvocation.ApplicableMethods.Cast(); + memberGroup = dynamicInvocation.ApplicableMethods.Cast(); + symbols = OneOrMany.Create(memberGroup); isDynamic = true; break; case BoundKind.DynamicCollectionElementInitializer: var collectionInit = (BoundDynamicCollectionElementInitializer)boundNode; Debug.Assert(collectionInit.ExpressionSymbol is null); - symbols = memberGroup = collectionInit.ApplicableMethods.Cast(); + memberGroup = collectionInit.ApplicableMethods.Cast(); + symbols = OneOrMany.Create(memberGroup); isDynamic = true; break; case BoundKind.DynamicIndexerAccess: var dynamicIndexer = (BoundDynamicIndexerAccess)boundNode; Debug.Assert(dynamicIndexer.ExpressionSymbol is null); - symbols = memberGroup = dynamicIndexer.ApplicableIndexers.Cast(); + memberGroup = dynamicIndexer.ApplicableIndexers.Cast(); + symbols = OneOrMany.Create(memberGroup); isDynamic = true; break; @@ -3643,7 +3646,8 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) case BoundKind.DynamicObjectCreationExpression: var objectCreation = (BoundDynamicObjectCreationExpression)boundNode; - symbols = memberGroup = objectCreation.ApplicableMethods.Cast(); + memberGroup = objectCreation.ApplicableMethods.Cast(); + symbols = OneOrMany.Create(memberGroup); isDynamic = true; break; @@ -3653,11 +3657,11 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) if ((object)boundObjectCreation.Constructor != null) { Debug.Assert(boundObjectCreation.ConstructorsGroup.Contains(boundObjectCreation.Constructor)); - symbols = ImmutableArray.Create(boundObjectCreation.Constructor); + symbols = OneOrMany.Create(boundObjectCreation.Constructor); } else if (boundObjectCreation.ConstructorsGroup.Length > 0) { - symbols = StaticCast.From(boundObjectCreation.ConstructorsGroup); + symbols = StaticCast.From(OneOrMany.Create(boundObjectCreation.ConstructorsGroup)); resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } @@ -3672,7 +3676,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) var containingMember = binder.ContainingMember(); var thisParam = GetThisParameter(boundNode.Type, containingType, containingMember, out resultKind); - symbols = thisParam != null ? ImmutableArray.Create(thisParam) : ImmutableArray.Empty; + symbols = thisParam != null ? OneOrMany.Create(thisParam) : OneOrMany.Empty; } break; @@ -3681,7 +3685,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) var fromEndIndexExpression = (BoundFromEndIndexExpression)boundNode; if ((object)fromEndIndexExpression.MethodOpt != null) { - symbols = ImmutableArray.Create(fromEndIndexExpression.MethodOpt); + symbols = OneOrMany.Create(fromEndIndexExpression.MethodOpt); } break; } @@ -3691,7 +3695,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) var rangeExpression = (BoundRangeExpression)boundNode; if ((object)rangeExpression.MethodOpt != null) { - symbols = ImmutableArray.Create(rangeExpression.MethodOpt); + symbols = OneOrMany.Create(rangeExpression.MethodOpt); } break; } @@ -3700,7 +3704,7 @@ public ILocalSymbol GetDeclaredSymbol(CatchDeclarationSyntax catchDeclaration) { if (boundNode.ExpressionSymbol is Symbol symbol) { - symbols = ImmutableArray.Create(symbol); + symbols = OneOrMany.Create(symbol); resultKind = boundNode.ResultKind; } } @@ -3779,7 +3783,7 @@ private static ParameterSymbol GetThisParameter(TypeSymbol typeOfThis, NamedType return thisParam; } - private static void GetSymbolsAndResultKind(BoundUnaryOperator unaryOperator, out bool isDynamic, ref LookupResultKind resultKind, ref ImmutableArray symbols) + private static void GetSymbolsAndResultKind(BoundUnaryOperator unaryOperator, out bool isDynamic, ref LookupResultKind resultKind, ref OneOrMany symbols) { UnaryOperatorKind operandType = unaryOperator.OperatorKind.OperandTypes(); isDynamic = unaryOperator.OperatorKind.IsDynamic(); @@ -3795,14 +3799,14 @@ private static void GetSymbolsAndResultKind(BoundUnaryOperator unaryOperator, ou { Debug.Assert((object)unaryOperator.MethodOpt == null && unaryOperator.OriginalUserDefinedOperatorsOpt.IsDefaultOrEmpty); UnaryOperatorKind op = unaryOperator.OperatorKind.Operator(); - symbols = ImmutableArray.Create(new SynthesizedIntrinsicOperatorSymbol(unaryOperator.Operand.Type.StrippedType(), - OperatorFacts.UnaryOperatorNameFromOperatorKind(op, isChecked: unaryOperator.OperatorKind.IsChecked()), - unaryOperator.Type.StrippedType())); + symbols = OneOrMany.Create(new SynthesizedIntrinsicOperatorSymbol(unaryOperator.Operand.Type.StrippedType(), + OperatorFacts.UnaryOperatorNameFromOperatorKind(op, isChecked: unaryOperator.OperatorKind.IsChecked()), + unaryOperator.Type.StrippedType())); resultKind = unaryOperator.ResultKind; } } - private static void GetSymbolsAndResultKind(BoundIncrementOperator increment, out bool isDynamic, ref LookupResultKind resultKind, ref ImmutableArray symbols) + private static void GetSymbolsAndResultKind(BoundIncrementOperator increment, out bool isDynamic, ref LookupResultKind resultKind, ref OneOrMany symbols) { UnaryOperatorKind operandType = increment.OperatorKind.OperandTypes(); isDynamic = increment.OperatorKind.IsDynamic(); @@ -3818,14 +3822,14 @@ private static void GetSymbolsAndResultKind(BoundIncrementOperator increment, ou { Debug.Assert((object)increment.MethodOpt == null && increment.OriginalUserDefinedOperatorsOpt.IsDefaultOrEmpty); UnaryOperatorKind op = increment.OperatorKind.Operator(); - symbols = ImmutableArray.Create(new SynthesizedIntrinsicOperatorSymbol(increment.Operand.Type.StrippedType(), - OperatorFacts.UnaryOperatorNameFromOperatorKind(op, isChecked: increment.OperatorKind.IsChecked()), - increment.Type.StrippedType())); + symbols = OneOrMany.Create(new SynthesizedIntrinsicOperatorSymbol(increment.Operand.Type.StrippedType(), + OperatorFacts.UnaryOperatorNameFromOperatorKind(op, isChecked: increment.OperatorKind.IsChecked()), + increment.Type.StrippedType())); resultKind = increment.ResultKind; } } - private static void GetSymbolsAndResultKind(BoundBinaryOperator binaryOperator, out bool isDynamic, ref LookupResultKind resultKind, ref ImmutableArray symbols) + private static void GetSymbolsAndResultKind(BoundBinaryOperator binaryOperator, out bool isDynamic, ref LookupResultKind resultKind, ref OneOrMany symbols) { BinaryOperatorKind operandType = binaryOperator.OperatorKind.OperandTypes(); BinaryOperatorKind op = binaryOperator.OperatorKind.Operator(); @@ -3851,18 +3855,18 @@ private static void GetSymbolsAndResultKind(BoundBinaryOperator binaryOperator, // Comparison of a nullable type with null, return corresponding operator for Object. var objectType = binaryOperator.Type.ContainingAssembly.GetSpecialType(SpecialType.System_Object); - symbols = ImmutableArray.Create(new SynthesizedIntrinsicOperatorSymbol(objectType, - OperatorFacts.BinaryOperatorNameFromOperatorKind(op, isChecked: binaryOperator.OperatorKind.IsChecked()), - objectType, - binaryOperator.Type)); + symbols = OneOrMany.Create(new SynthesizedIntrinsicOperatorSymbol(objectType, + OperatorFacts.BinaryOperatorNameFromOperatorKind(op, isChecked: binaryOperator.OperatorKind.IsChecked()), + objectType, + binaryOperator.Type)); } else { - symbols = ImmutableArray.Create(GetIntrinsicOperatorSymbol(op, isDynamic, - binaryOperator.Left.Type, - binaryOperator.Right.Type, - binaryOperator.Type, - binaryOperator.OperatorKind.IsChecked())); + symbols = OneOrMany.Create(GetIntrinsicOperatorSymbol(op, isDynamic, + binaryOperator.Left.Type, + binaryOperator.Right.Type, + binaryOperator.Type, + binaryOperator.OperatorKind.IsChecked())); } resultKind = binaryOperator.ResultKind; @@ -3898,7 +3902,7 @@ private static Symbol GetIntrinsicOperatorSymbol(BinaryOperatorKind op, bool isD returnType); } - private static void GetSymbolsAndResultKind(BoundCompoundAssignmentOperator compoundAssignment, out bool isDynamic, ref LookupResultKind resultKind, ref ImmutableArray symbols) + private static void GetSymbolsAndResultKind(BoundCompoundAssignmentOperator compoundAssignment, out bool isDynamic, ref LookupResultKind resultKind, ref OneOrMany symbols) { BinaryOperatorKind operandType = compoundAssignment.Operator.Kind.OperandTypes(); BinaryOperatorKind op = compoundAssignment.Operator.Kind.Operator(); @@ -3915,30 +3919,30 @@ private static void GetSymbolsAndResultKind(BoundCompoundAssignmentOperator comp { Debug.Assert((object)compoundAssignment.Operator.Method == null && compoundAssignment.OriginalUserDefinedOperatorsOpt.IsDefaultOrEmpty); - symbols = ImmutableArray.Create(GetIntrinsicOperatorSymbol(op, isDynamic, - compoundAssignment.Operator.LeftType, - compoundAssignment.Operator.RightType, - compoundAssignment.Operator.ReturnType, - compoundAssignment.Operator.Kind.IsChecked())); + symbols = OneOrMany.Create(GetIntrinsicOperatorSymbol(op, isDynamic, + compoundAssignment.Operator.LeftType, + compoundAssignment.Operator.RightType, + compoundAssignment.Operator.ReturnType, + compoundAssignment.Operator.Kind.IsChecked())); resultKind = compoundAssignment.ResultKind; } } - private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolOpt, ImmutableArray originalCandidates, out ImmutableArray symbols, out LookupResultKind resultKind) + private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolOpt, ImmutableArray originalCandidates, out OneOrMany symbols, out LookupResultKind resultKind) { if (!ReferenceEquals(symbolOpt, null)) { - symbols = ImmutableArray.Create(symbolOpt); + symbols = OneOrMany.Create(symbolOpt); resultKind = node.ResultKind; } else if (!originalCandidates.IsDefault) { - symbols = StaticCast.From(originalCandidates); + symbols = StaticCast.From(OneOrMany.Create(originalCandidates)); resultKind = node.ResultKind; } else { - symbols = ImmutableArray.Empty; + symbols = OneOrMany.Empty; resultKind = LookupResultKind.Empty; } } @@ -3951,7 +3955,7 @@ private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolO BoundNode boundNodeForSyntacticParent, Binder binderOpt, ref LookupResultKind resultKind, - ref ImmutableArray symbols, + ref OneOrMany symbols, ref ImmutableArray memberGroup) { NamedTypeSymbol typeSymbol = null; @@ -3970,7 +3974,7 @@ private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolO case BoundKind.Attribute: BoundAttribute boundAttribute = (BoundAttribute)boundNodeForSyntacticParent; - if (unwrappedSymbols.Length == 1 && unwrappedSymbols[0].Kind == SymbolKind.NamedType) + if (unwrappedSymbols.Count == 1 && unwrappedSymbols[0].Kind == SymbolKind.NamedType) { Debug.Assert(resultKind != LookupResultKind.Viable || TypeSymbol.Equals((TypeSymbol)unwrappedSymbols[0], boundAttribute.Type.GetNonErrorGuess(), TypeCompareKind.ConsiderEverything2)); @@ -3983,7 +3987,7 @@ private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolO case BoundKind.BadExpression: BoundBadExpression boundBadExpression = (BoundBadExpression)boundNodeForSyntacticParent; - if (unwrappedSymbols.Length == 1) + if (unwrappedSymbols.Count == 1) { resultKind = resultKind.WorseResultKind(boundBadExpression.ResultKind); typeSymbol = unwrappedSymbols[0] as NamedTypeSymbol; @@ -4004,7 +4008,7 @@ private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolO MethodSymbol constructorOpt, Binder binderOpt, ref LookupResultKind resultKind, - ref ImmutableArray symbols, + ref OneOrMany symbols, ref ImmutableArray memberGroup) { Debug.Assert(lowestBoundNode != null); @@ -4045,11 +4049,11 @@ private static void GetSymbolsAndResultKind(BoundExpression node, Symbol symbolO if ((object)constructorOpt != null) { Debug.Assert(candidateConstructors.Contains(constructorOpt)); - symbols = ImmutableArray.Create(constructorOpt); + symbols = OneOrMany.Create(constructorOpt); } else if (candidateConstructors.Length > 0) { - symbols = StaticCast.From(candidateConstructors); + symbols = StaticCast.From(OneOrMany.Create(candidateConstructors)); Debug.Assert(resultKind != LookupResultKind.Viable); resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } @@ -4214,7 +4218,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // If the parent node of the method group syntax node provides information (such as arguments) // that allows us to return more specific symbols (a specific overload or applicable candidates) // we return these. The complete set of symbols of the method group is then returned in methodGroup parameter. - private ImmutableArray GetMethodGroupSemanticSymbols( + private OneOrMany GetMethodGroupSemanticSymbols( BoundMethodGroup boundNode, BoundNode boundNodeForSyntacticParent, Binder binderOpt, @@ -4224,7 +4228,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu { Debug.Assert(binderOpt != null || IsInTree(boundNode.Syntax)); - ImmutableArray symbols = ImmutableArray.Empty; + OneOrMany symbols = OneOrMany.Empty; resultKind = boundNode.ResultKind; if (resultKind == LookupResultKind.Empty) @@ -4289,7 +4293,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu method = ReducedExtensionMethodSymbol.Create(method); } - symbols = ImmutableArray.Create((Symbol)method); + symbols = OneOrMany.Create((Symbol)method); resultKind = conversion.ResultKind; } else @@ -4301,7 +4305,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu case BoundKind.DynamicInvocation: var dynamicInvocation = (BoundDynamicInvocation)boundNodeForSyntacticParent; - symbols = dynamicInvocation.ApplicableMethods.Cast(); + symbols = OneOrMany.Create(dynamicInvocation.ApplicableMethods.Cast()); isDynamic = true; break; @@ -4309,7 +4313,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // If the bad expression has symbol(s) from this method group, it better indicates any problems. ImmutableArray myMethodGroup = methodGroup; - symbols = ((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray((sym, myMethodGroup) => myMethodGroup.Contains(sym), myMethodGroup); + symbols = OneOrMany.Create(((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray((sym, myMethodGroup) => myMethodGroup.Contains(sym), myMethodGroup)); if (symbols.Any()) { resultKind = ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind; @@ -4317,13 +4321,13 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu break; case BoundKind.NameOfOperator: - symbols = methodGroup; + symbols = OneOrMany.Create(methodGroup); resultKind = resultKind.WorseResultKind(LookupResultKind.MemberGroup); break; default: - symbols = methodGroup; - if (symbols.Length > 0) + symbols = OneOrMany.Create(methodGroup); + if (symbols.Count > 0) { resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } @@ -4337,8 +4341,8 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // not specified (see SemanticModel.GetSymbolInfoForNode). However, if there's exactly // one candidate, then we should probably succeed. - symbols = methodGroup; - if (symbols.Length > 0) + symbols = OneOrMany.Create(methodGroup); + if (symbols.Count > 0) { resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } @@ -4349,7 +4353,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // If we didn't find a better set of symbols, then assume this is a method group that didn't // get resolved. Return all members of the method group, with a resultKind of OverloadResolutionFailure // (unless the method group already has a worse result kind). - symbols = methodGroup; + symbols = OneOrMany.Create(methodGroup); if (!isDynamic && resultKind > LookupResultKind.OverloadResolutionFailure) { resultKind = LookupResultKind.OverloadResolutionFailure; @@ -4360,7 +4364,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu } // NB: It is not safe to pass a null binderOpt during speculative binding. - private ImmutableArray GetPropertyGroupSemanticSymbols( + private OneOrMany GetPropertyGroupSemanticSymbols( BoundPropertyGroup boundNode, BoundNode boundNodeForSyntacticParent, Binder binderOpt, @@ -4369,7 +4373,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu { Debug.Assert(binderOpt != null || IsInTree(boundNode.Syntax)); - ImmutableArray symbols = ImmutableArray.Empty; + OneOrMany symbols = OneOrMany.Empty; resultKind = boundNode.ResultKind; if (resultKind == LookupResultKind.Empty) @@ -4395,13 +4399,13 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu if (indexer.OriginalIndexersOpt.IsDefault) { // Overload resolution succeeded. - symbols = ImmutableArray.Create(indexer.Indexer); + symbols = OneOrMany.Create(indexer.Indexer); resultKind = LookupResultKind.Viable; } else { resultKind = indexer.ResultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); - symbols = StaticCast.From(indexer.OriginalIndexersOpt); + symbols = StaticCast.From(OneOrMany.Create(indexer.OriginalIndexersOpt)); } } break; @@ -4410,7 +4414,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // If the bad expression has symbol(s) from this property group, it better indicates any problems. ImmutableArray myPropertyGroup = propertyGroup; - symbols = ((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray((sym, myPropertyGroup) => myPropertyGroup.Contains(sym), myPropertyGroup); + symbols = OneOrMany.Create(((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray((sym, myPropertyGroup) => myPropertyGroup.Contains(sym), myPropertyGroup)); if (symbols.Any()) { resultKind = ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind; @@ -4426,7 +4430,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // one candidate, then we should probably succeed. // If we're speculatively binding and there's exactly one candidate, then we should probably succeed. - symbols = propertyGroup; + symbols = OneOrMany.Create(propertyGroup); } if (!symbols.Any()) @@ -4434,7 +4438,7 @@ private static ImmutableArray FilterOverriddenOrHiddenMethods(Immu // If we didn't find a better set of symbols, then assume this is a property group that didn't // get resolved. Return all members of the property group, with a resultKind of OverloadResolutionFailure // (unless the property group already has a worse result kind). - symbols = propertyGroup; + symbols = OneOrMany.Create(propertyGroup); if (resultKind > LookupResultKind.OverloadResolutionFailure) { resultKind = LookupResultKind.OverloadResolutionFailure; @@ -4719,7 +4723,7 @@ internal static ImmutableArray GetReducedAndFilteredMethodGroupSym /// If the call represents an extension method invocation with an explicit receiver, return the original /// methods as ReducedExtensionMethodSymbols. Otherwise, return the original methods unchanged. /// - private static ImmutableArray CreateReducedExtensionMethodsFromOriginalsIfNecessary(BoundCall call, CSharpCompilation compilation) + private static OneOrMany CreateReducedExtensionMethodsFromOriginalsIfNecessary(BoundCall call, CSharpCompilation compilation) { var methods = call.OriginalMethodsOpt; TypeSymbol extensionThisType = null; @@ -4748,7 +4752,7 @@ private static ImmutableArray CreateReducedExtensionMethodsFromOri AddReducedAndFilteredMethodGroupSymbol(methodBuilder, filteredMethodBuilder, method, default(ImmutableArray), extensionThisType, compilation); } methodBuilder.Free(); - return filteredMethodBuilder.ToImmutableAndFree(); + return filteredMethodBuilder.ToOneOrManyAndFree(); } /// @@ -4756,7 +4760,7 @@ private static ImmutableArray CreateReducedExtensionMethodsFromOri /// ReducedExtensionMethodSymbol if it can be constructed. Otherwise, return the /// original call method. /// - private ImmutableArray CreateReducedExtensionMethodIfPossible(BoundCall call) + private OneOrMany CreateReducedExtensionMethodIfPossible(BoundCall call) { var method = call.Method; Debug.Assert((object)method != null); @@ -4770,10 +4774,10 @@ private ImmutableArray CreateReducedExtensionMethodIfPossible(BoundCall // type, we should also return the original call method. method = reduced ?? method; } - return ImmutableArray.Create(method); + return OneOrMany.Create(method); } - private ImmutableArray CreateReducedExtensionMethodIfPossible(BoundDelegateCreationExpression delegateCreation, BoundExpression receiverOpt) + private OneOrMany CreateReducedExtensionMethodIfPossible(BoundDelegateCreationExpression delegateCreation, BoundExpression receiverOpt) { var method = delegateCreation.MethodOpt; Debug.Assert((object)method != null); @@ -4783,7 +4787,7 @@ private ImmutableArray CreateReducedExtensionMethodIfPossible(BoundDeleg MethodSymbol reduced = method.ReduceExtensionMethod(receiverOpt.Type, Compilation); method = reduced ?? method; } - return ImmutableArray.Create(method); + return OneOrMany.Create(method); } /// diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs index 8536e0ef6a327..97a3154e0ecba 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs @@ -38,7 +38,7 @@ private NodeMapBuilder(OrderPreservingMultiDictionary map /// The root of the bound tree. /// The cache. /// The syntax node where to add bound nodes for. - public static void AddToMap(BoundNode root, Dictionary> map, SyntaxTree tree, SyntaxNode node = null) + public static void AddToMap(BoundNode root, Dictionary> map, SyntaxTree tree, SyntaxNode node = null) { Debug.Assert(node == null || root == null || !(root.Syntax is StatementSyntax), "individually added nodes are not supposed to be statements."); @@ -74,8 +74,8 @@ public static void AddToMap(BoundNode root, Dictionary> _guardedBoundNodeMap = new Dictionary>(); + private readonly Dictionary> _guardedBoundNodeMap = new Dictionary>(); private readonly Dictionary _guardedIOperationNodeMap = new Dictionary(); private Dictionary _lazyGuardedSynthesizedStatementsMap; private NullableWalker.SnapshotManager _lazySnapshotManager; @@ -522,7 +522,7 @@ internal BoundNode GetUpperBoundNode(CSharpSyntaxNode node, bool promoteToBindab // The bound nodes are stored in the map from highest to lowest, so the first bound node is the highest. var boundNodes = GetBoundNodes(node); - if (boundNodes.Length == 0) + if (boundNodes.Count == 0) { return null; } @@ -543,7 +543,7 @@ internal BoundNode GetLowerBoundNode(CSharpSyntaxNode node) // The bound nodes are stored in the map from highest to lowest, so the last bound node is the lowest. var boundNodes = GetBoundNodes(node); - if (boundNodes.Length == 0) + if (boundNodes.Count == 0) { return null; } @@ -553,9 +553,9 @@ internal BoundNode GetLowerBoundNode(CSharpSyntaxNode node) } } - private static BoundNode GetLowerBoundNode(ImmutableArray boundNodes) + private static BoundNode GetLowerBoundNode(OneOrMany boundNodes) { - return boundNodes[boundNodes.Length - 1]; + return boundNodes[boundNodes.Count - 1]; } public sealed override ImmutableArray GetSyntaxDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken)) @@ -1420,25 +1420,25 @@ private BoundStatement GuardedGetSynthesizedStatementFromMap(StatementSyntax nod return null; } - private ImmutableArray GuardedGetBoundNodesFromMap(CSharpSyntaxNode node) + private OneOrMany GuardedGetBoundNodesFromMap(CSharpSyntaxNode node) { Debug.Assert(_nodeMapLock.IsWriteLockHeld || _nodeMapLock.IsReadLockHeld); - ImmutableArray result; - return _guardedBoundNodeMap.TryGetValue(node, out result) ? result : default(ImmutableArray); + OneOrMany result; + return _guardedBoundNodeMap.TryGetValue(node, out result) ? result : OneOrMany.Empty; } /// /// Internal for test purposes only /// - internal ImmutableArray TestOnlyTryGetBoundNodesFromMap(CSharpSyntaxNode node) + internal OneOrMany TestOnlyTryGetBoundNodesFromMap(CSharpSyntaxNode node) { - ImmutableArray result; - return _guardedBoundNodeMap.TryGetValue(node, out result) ? result : default(ImmutableArray); + OneOrMany result; + return _guardedBoundNodeMap.TryGetValue(node, out result) ? result : OneOrMany.Empty; } // Adds every syntax/bound pair in a tree rooted at the given bound node to the map, and the // performs a lookup of the given syntax node in the map. - private ImmutableArray GuardedAddBoundTreeAndGetBoundNodeFromMap(CSharpSyntaxNode syntax, BoundNode bound) + private OneOrMany GuardedAddBoundTreeAndGetBoundNodeFromMap(CSharpSyntaxNode syntax, BoundNode bound) { Debug.Assert(_nodeMapLock.IsWriteLockHeld); @@ -1457,8 +1457,8 @@ private ImmutableArray GuardedAddBoundTreeAndGetBoundNodeFromMap(CSha Debug.Assert(syntax != _root || _guardedBoundNodeMap.ContainsKey(bound.Syntax)); } - ImmutableArray result; - return _guardedBoundNodeMap.TryGetValue(syntax, out result) ? result : default(ImmutableArray); + OneOrMany result; + return _guardedBoundNodeMap.TryGetValue(syntax, out result) ? result : OneOrMany.Empty; } protected void UnguardedAddBoundTreeForStandaloneSyntax(SyntaxNode syntax, BoundNode bound, NullableWalker.SnapshotManager manager = null, ImmutableDictionary remappedSymbols = null) @@ -1620,7 +1620,7 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) { // Have we already cached a bound node for it? // If not, bind the outermost expression containing the lambda and then fill in the map. - ImmutableArray nodes; + OneOrMany nodes; EnsureNullabilityAnalysisPerformedIfNecessary(); @@ -1629,7 +1629,7 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) nodes = GuardedGetBoundNodesFromMap(lambdaOrQuery); } - if (!nodes.IsDefaultOrEmpty) + if (!nodes.IsEmpty) { return GetLowerBoundNode(nodes); } @@ -1666,7 +1666,7 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) nodes = GuardedGetBoundNodesFromMap(lambdaOrQuery); } - if (!nodes.IsDefaultOrEmpty) + if (!nodes.IsEmpty) { // If everything is working as expected we should end up here because binding the enclosing lambda // should also take care of binding and caching this lambda. @@ -1688,7 +1688,7 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) nodes = GuardedAddBoundTreeAndGetBoundNodeFromMap(lambdaOrQuery, boundOuterExpression); } - if (!nodes.IsDefaultOrEmpty) + if (!nodes.IsEmpty) { return GetLowerBoundNode(nodes); } @@ -2037,7 +2037,7 @@ private Binder GetBinderToBindNode(CSharpSyntaxNode nodeToBind) /// Get all bounds nodes associated with a node, ordered from highest to lowest in the bound tree. /// Strictly speaking, the order is that of a pre-order traversal of the bound tree. /// - internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) + internal OneOrMany GetBoundNodes(CSharpSyntaxNode node) { // If this method is called with a null parameter, that implies that the Root should be // bound, but make sure that the Root is bindable. @@ -2061,14 +2061,14 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) // reader-writer lock. // // Have we already got the desired bound node in the mutable map? If so, return it. - ImmutableArray results; + OneOrMany results; using (_nodeMapLock.DisposableRead()) { results = GuardedGetBoundNodesFromMap(node); } - if (!results.IsDefaultOrEmpty) + if (!results.IsEmpty) { return results; } @@ -2088,7 +2088,7 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) results = GuardedAddBoundTreeAndGetBoundNodeFromMap(node, boundStatement); } - if (!results.IsDefaultOrEmpty) + if (!results.IsEmpty) { return results; } @@ -2108,7 +2108,7 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) results = GuardedGetBoundNodesFromMap(node); } - if (results.IsDefaultOrEmpty) + if (results.IsEmpty) { // https://github.com/dotnet/roslyn/issues/35038: We have to run analysis on this node in some manner using (_nodeMapLock.DisposableWrite()) @@ -2118,7 +2118,7 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) results = GuardedGetBoundNodesFromMap(node); } - if (!results.IsDefaultOrEmpty) + if (!results.IsEmpty) { return results; } @@ -2128,7 +2128,7 @@ internal ImmutableArray GetBoundNodes(CSharpSyntaxNode node) return results; } - return ImmutableArray.Empty; + return OneOrMany.Empty; } // some nodes don't have direct semantic meaning by themselves and so we need to bind a different node that does @@ -2430,9 +2430,9 @@ private BoundNode TryGetBoundNodeFromMap(CSharpSyntaxNode node) { if (node.SyntaxTree == _semanticModel.SyntaxTree) { - ImmutableArray boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node); + OneOrMany boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node); - if (!boundNodes.IsDefaultOrEmpty) + if (!boundNodes.IsEmpty) { // Already bound. Return the top-most bound node associated with the statement. return boundNodes[0]; diff --git a/src/Compilers/CSharp/Portable/Compilation/SymbolInfoFactory.cs b/src/Compilers/CSharp/Portable/Compilation/SymbolInfoFactory.cs index 06a6f7c240a1f..ad650e8980a15 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SymbolInfoFactory.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SymbolInfoFactory.cs @@ -9,6 +9,7 @@ using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp @@ -16,23 +17,26 @@ namespace Microsoft.CodeAnalysis.CSharp internal static class SymbolInfoFactory { internal static SymbolInfo Create(ImmutableArray symbols, LookupResultKind resultKind, bool isDynamic) + => Create(OneOrMany.Create(symbols.NullToEmpty()), resultKind, isDynamic); + + internal static SymbolInfo Create(OneOrMany symbols, LookupResultKind resultKind, bool isDynamic) { if (isDynamic) { - if (symbols.Length == 1) + if (symbols.Count == 1) { return new SymbolInfo(symbols[0].GetPublicSymbol(), CandidateReason.LateBound); } else { - return new SymbolInfo(symbols.GetPublicSymbols(), CandidateReason.LateBound); + return new SymbolInfo(getPublicSymbols(symbols), CandidateReason.LateBound); } } else if (resultKind == LookupResultKind.Viable) { - if (symbols.Length > 0) + if (symbols.Count > 0) { - Debug.Assert(symbols.Length == 1); + Debug.Assert(symbols.Count == 1); return new SymbolInfo(symbols[0].GetPublicSymbol()); } else @@ -42,7 +46,16 @@ internal static SymbolInfo Create(ImmutableArray symbols, LookupResultKi } else { - return new SymbolInfo(symbols.GetPublicSymbols(), (symbols.Length > 0) ? resultKind.ToCandidateReason() : CandidateReason.None); + return new SymbolInfo(getPublicSymbols(symbols), (symbols.Count > 0) ? resultKind.ToCandidateReason() : CandidateReason.None); + } + + static ImmutableArray getPublicSymbols(OneOrMany symbols) + { + var result = ArrayBuilder.GetInstance(symbols.Count); + foreach (var symbol in symbols) + result.Add(symbol.GetPublicSymbol()); + + return result.ToImmutableAndFree(); } } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 97e66bb433065..08b608bf72086 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + Identifikátor {0} je v tomto kontextu nejednoznačný mezi typem {1} a parametrem {2}. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Parametr {0}, který má typ podobný odkazu, nejde použít uvnitř anonymní metody, výrazu lambda, výrazu dotazu nebo místní funkce. Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Anonymní metody, výrazy lambda, výrazy dotazů a místní funkce uvnitř struktury nemají přístup k parametru primárního konstruktoru, který se používá také uvnitř členu instance. Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Anonymní metody, výrazy lambda, výrazy dotazů a místní funkce uvnitř členu instance struktury nemají přístup k parametru primárního konstruktoru. @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Parametr primárního konstruktoru typu jen pro čtení nejde přiřadit (s výjimkou nastavovacího kódu typu jenom pro inicializaci nebo inicializátoru proměnné). Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Členy parametru primárního konstruktoru {0} typu jen pro čtení nejde změnit (s výjimkou nastavovacího kódu typu jenom pro inicializaci nebo inicializátoru proměnné). @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Arm výrazu přepínače nezačíná klíčovým slovem case. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + Použití aliasu nemůže být odkazový typ s možnou hodnotou null. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Prostředek použitého příkazu typu {0} nejde použít v asynchronních metodách ani v asynchronních výrazech lambda. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + Použitý alias nemůže být typu ref. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + Modifikátor „static“ musí předcházet modifikátoru „unsafe“. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Pouze „using static“ nebo „using alias“ může být „nebezpečný“. @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + Očekává se konstantní hodnota typu „{0}“. @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - V typeof v atributu se nepodporuje používání typu ukazatele funkce. + Použití typu ukazatele funkce v tomto kontextu není podporováno. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + V tomto kontextu nejde použít parametr primárního konstruktoru {0}. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Seznam parametrů může mít jenom částečná deklarace jednoho záznamu. + Seznam parametrů může obsahovat pouze jedna deklarace částečného typu. @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Konstruktor deklarovaný v „record struct“ se seznamem parametrů musí mít inicializátor „this“, který volá primární konstruktor nebo explicitně deklarovaný konstruktor. + Konstruktor deklarovaný ve „struct“ se seznamem parametrů musí mít inicializátor „this“, který volá primární konstruktor nebo explicitně deklarovaný konstruktor. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Parametr primárního konstruktoru typu jen pro čtení nejde použít jako hodnotu odkazu nebo výstupu (s výjimkou nastavovacího kódu typu jenom pro inicializaci nebo inicializátoru proměnné). Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Členy parametru primárního konstruktoru {0} typu jen pro čtení nejde použít jako hodnotu odkazu nebo výstupu (s výjimkou nastavovacího kódu typu jenom pro inicializaci nebo inicializátoru proměnné). @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Parametr primárního konstruktoru {0} nejde vrátit pomocí odkazu. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Parametr primárního konstruktoru typu jen pro čtení nejde vrátit zapisovatelným odkazem. Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Členy parametru primárního konstruktoru {0} typu jen pro čtení nejde vrátit zapisovatelným odkazem. @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + Parametr primárního konstruktoru struktury {0} typu{1} způsobuje cyklus v rozložení struktury. @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Neočekávaný seznam parametrů. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + {0} se definuje v modulu s nerozpoznanou verzí RefSafetyRulesAttribute, očekává se hodnota 11. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Uvnitř členu instance nejde použít parametr primárního konstruktoru {0} typu odkaz, výstup nebo vstup. Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Nejde použít parametr primárního konstruktoru {0}, který má uvnitř členu instance typ podobný odkazu. @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + primární konstruktory @@ -1994,7 +1994,7 @@ using type alias - using type alias + pomocí aliasu typu @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Operátor „&“ by se neměl používat u parametrů nebo místních proměnných v asynchronních metodách. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Operátor „&“ by se neměl používat u parametrů nebo místních proměnných v asynchronních metodách. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Parametr {0} se zachytil do stavu nadřazeného typu a jeho hodnota se také předala základnímu konstruktoru. Hodnotu může zachytit i základní třída. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Parametr se zachytil do stavu nadřazeného typu a jeho hodnota se také předala základnímu konstruktoru. Hodnotu může zachytit i základní třída. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Konstruktor deklarovaný v záznamu se seznamem parametrů musí mít inicializátor konstruktoru this. + Konstruktor deklarovaný v typu se seznamem parametrů musí mít inicializátor konstruktoru this. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + Parametr {0} je nepřečtený. Parameter is unread. - Parameter is unread. + Parametr je nepřečtený. @@ -10381,22 +10381,22 @@ Potlačení upozornění zvažte jenom v případě, když určitě nechcete če The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + Zadaný řetězec verze „{0}“ neodpovídá požadovanému formátu – hlavní_verze[.podverze[.build[.revize]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + Zadaný řetězec verze „{0}“ obsahuje zástupné znaky, které nejsou kompatibilní s determinismem. Odeberte zástupné znaky z řetězce verze nebo zakažte determinismus pro tuto kompilaci. The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + Zadaný řetězec verze „{0}“ neodpovídá požadovanému formátu – major.minor.build.revision (bez zástupných znaků). The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + Zadaný řetězec verze „{0}“ neodpovídá doporučenému formátu – major.minor.build.revision. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 4bcd4e78a597c..93b95e24b50f4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + Bezeichner „{0}“ ist zwischen Typ „{1}“ und Parameter „{2}“ in diesem Kontext mehrdeutig. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Der Parameter „{0}“, der einen ref-ähnlichen Typ aufweist, kann nicht innerhalb einer anonymen Methode, eines Lambdaausdrucks, eines Abfrageausdrucks oder einer lokalen Funktion verwendet werden. Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Anonyme Methoden, Lambdaausdrücke, Abfrageausdrücke und lokale Funktionen innerhalb einer Struktur können nicht auf den primären Konstruktorparameter zugreifen, der auch innerhalb eines Instanzmembers verwendet wird. Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Anonyme Methoden, Lambdaausdrücken, Abfrageausdrücke und lokale Funktionen innerhalb eines Instanzmembers einer Struktur können nicht auf den primären Konstruktorparameter zugreifen. @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Einem primären Konstruktorparameter eines schreibgeschützten Typs kann nichts zugewiesen werden (mit Ausnahme des init-only-Setters des Typs oder eines Variableninitialisierers). Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Member des primären Konstruktorparameters „{0}“ eines schreibgeschützten Typs können nicht geändert werden (mit Ausnahme des init-only-Setters des Typs oder eines Variableninitialisierers). @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Ein Switch-Ausdrucksarm beginnt nicht mit einem 'case'-Schlüsselwort. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + Die Verwendung des Alias darf kein Verweistyp sein, der NULL-Werte zulässt. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Eine using-Anweisungsressource vom Typ „{0}“ kann nicht in asynchronen Methoden oder asynchronen Lambdaausdrücken verwendet werden. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + Die Verwendung des Alias darf nicht vom Typ 'ref' sein. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + Der Modifizierer 'static' muss dem Modifizierer 'unsicher' vorangestellt sein. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Nur ein "using static" oder "using alias" kann "unsicher" sein. @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - Die Verwendung eines Funktionszeigertyps in "typeof" in einem Attribut wird nicht unterstützt. + Die Verwendung eines Funktionszeigertyps in diesem Kontext wird nicht unterstützt. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + Der primäre Konstruktorparameter „{0}“ kann in diesem Kontext nicht verwendet werden. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Nur eine partielle Deklaration eines einzelnen Datensatzes darf eine Parameterliste aufweisen. + Nur eine einzelne partielle Typdeklaration darf eine Parameterliste aufweisen. @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Ein in „record struct“ mit Parameterliste deklarierter Konstruktor muss über einen „this“-Initialisierer verfügen, der den primären Konstruktor oder einen explizit deklarierten Konstruktor aufruft. + Ein in „struct“ mit Parameterliste deklarierter Konstruktor muss über einen „this“-Initialisierer verfügen, der den primären Konstruktor oder einen explizit deklarierten Konstruktor aufruft. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Ein primärer Konstruktorparameter eines schreibgeschützten Typs kann nicht als ref- oder out-Wert verwendet werden (mit Ausnahme eines init-only-Setters des Typs oder eines Variableninitialisierers). Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Member des primären Konstruktorparameters „{0}“ eines schreibgeschützten Typs können nicht als ref- oder out-Wert verwendet werden (außer init-only-Setter des Typs oder eines Variableninitialisierers). @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Der primäre Konstruktorparameter „{0}“ kann nicht durch Verweis zurückgegeben werden. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Ein primärer Konstruktorparameter eines schreibgeschützten Typs kann nicht als beschreibbarer Verweis zurückgegeben werden. Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Member des primären Konstruktorparameters „{0}“ eines schreibgeschützten Typs können nicht durch einen beschreibbaren Verweis zurückgegeben werden. @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + Der primäre Strukturkonstruktorparameter „{0}“ vom Typ „{1}“ verursacht eine Schleife im struct-Layout. @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Unerwartete Parameterliste. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + „{0}“ ist in einem Modul mit einer unbekannten RefSafetyRulesAttribute-Version definiert, erwartet wird „11“. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Der ref-, out- oder in-primäre Konstruktorparameter „{0}“ kann nicht innerhalb eines Instanzmembers verwendet werden. Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Der primäre Konstruktorparameter „{0}“, der einen ref-ähnlichen Typ innerhalb eines Instanzmembers aufweist, kann nicht verwendet werden. @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + primäre Konstruktoren @@ -1994,7 +1994,7 @@ using type alias - using type alias + Typ-Alias wird verwendet @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Der Operator '&' sollte nicht für Parameter oder lokale Variablen in asynchronen Methoden verwendet werden. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Der Operator '&' sollte nicht für Parameter oder lokale Variablen in asynchronen Methoden verwendet werden. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Der Parameter „{0}“ wird in den Zustand des einschließenden Typs erfasst und sein Wert wird auch an den Basiskonstruktor übergeben. Der Wert kann auch von der Basisklasse erfasst werden. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Der Parameter wird im Zustand des einschließenden Typs erfasst und sein Wert wird auch an den Basiskonstruktor übergeben. Der Wert kann auch von der Basisklasse erfasst werden. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Ein Konstruktor, der in einem Datensatz mit Parameterliste deklariert ist, muss über den Konstruktorinitialisierer "this" verfügen. + Ein Konstruktor, der in einem Typ mit Parameterliste deklariert ist, muss über den Konstruktorinitialisierer „this“ verfügen. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + Der Parameter „{0}“ ist ungelesen. Parameter is unread. - Parameter is unread. + Der Parameter ist ungelesen. @@ -10381,22 +10381,22 @@ Sie sollten das Unterdrücken der Warnung nur in Betracht ziehen, wenn Sie siche The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + Die angegebene Versionszeichenfolge '{0}' entspricht nicht dem erforderlichen Format: Hauptversion[.Nebenversion[.Build[.Revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + Die angegebene Versionszeichenfolge '{0}' enthält Platzhalter, die mit Determinismus nicht kompatibel sind. Entfernen Sie die Platzhalter aus der Versionszeichenfolge, oder deaktivieren Sie Determinismus für diese Kompilierung. The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + Die angegebene Versionszeichenfolge '{0}' weist nicht das erforderliche Format auf: Hauptversion.Nebenversion.Build.Revision (ohne Platzhalter) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + Die angegebene Versionszeichenfolge '{0}' entspricht nicht dem empfohlenen Format: Hauptversion.Nebenversion.Build.Revision diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 8fe422c861086..4f8f403b1ec52 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + El identificador '{0}' es ambiguo entre el tipo '{1}' y el parámetro '{2}' en este contexto. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + No se puede usar el parámetro '{0}' que tiene un tipo de tipo ref dentro de un método anónimo, una expresión lambda, una expresión de consulta o una función local Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Los métodos anónimos, las expresiones lambda, las expresiones de consulta y las funciones locales dentro de una estructura no pueden tener acceso al parámetro de constructor principal que también se usa dentro de un miembro de instancia. Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Los métodos anónimos, las expresiones lambda, las expresiones de consulta y las funciones locales dentro de un miembro de instancia de un struct no pueden tener acceso al parámetro del constructor principal @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + No se puede asignar un parámetro de constructor principal de un tipo de solo lectura (excepto en el establecedor de solo inicialización del tipo o un inicializador de variable) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Los miembros del parámetro de constructor principal '{0}' de un tipo de solo lectura no se pueden modificar (excepto en el establecedor de solo inicialización del tipo o un inicializador de variable) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Un brazo de expresión de cambio no comienza con una palabra clave ''caso''. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + El uso de alias no puede ser un tipo de referencia que acepte valores NULL. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Un recurso de instrucción using de tipo '{0}' no se puede usar en métodos asincrónicos ni expresiones lambda asincrónicas. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + El uso de alias no puede ser un tipo 'ref'. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + El modificador ''estático'' debe preceder al modificador ''No seguro''. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Solo un ''usando estática'' o ''usando alias'' puede ser ''No seguro''. @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + Se espera un valor constante de tipo '{0}' @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - No se admite el uso de un tipo de puntero de función como valor "typeof" de un atributo. + No se admite el uso de un tipo de puntero de función en este contexto. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + No se puede usar el parámetro de constructor principal '{0}' en este contexto. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Solo una declaración parcial de un registro puede tener una lista de parámetros + Solo una declaración de tipo parcial puede tener una lista de parámetros @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Un constructor declarado en un 'record struct' con lista de parámetros debe tener un inicializador 'this' que llame al constructor principal o a un constructor declarado explícitamente. + Un constructor declarado en una `struct' con una lista de parámetros debe tener un inicializador `this' que llame al constructor primario, o a un constructor declarado explícitamente. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Un parámetro de constructor principal de un tipo de solo lectura no se puede usar como valor ref o out (excepto en el establecedor de solo inicialización del tipo o un inicializador de variable) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Los miembros del parámetro de constructor principal '{0}' de un tipo de solo lectura no se pueden usar como valor ref o out (excepto en el establecedor de solo inicialización del tipo o un inicializador de variable) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + No se puede devolver el parámetro de constructor principal '{0}' por referencia. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Una referencia grabable no puede devolver un parámetro de constructor principal de un tipo de solo lectura Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Los miembros del parámetro de constructor principal '{0}' de un tipo de solo lectura no se pueden devolver mediante una referencia grabable @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + El parámetro de constructor principal de struct '{0}' de tipo '{1}' provoca un ciclo en el diseño de struct @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Lista de parámetros inesperada. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}' se define en un módulo con una versión refSafetyRulesAttribute no reconocida, que espera '11'. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + No se puede usar ref, out o en el parámetro de constructor principal '{0}' dentro de un miembro de instancia Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + No se puede usar el parámetro de constructor principal '{0}' que tiene un tipo ref-like dentro de un miembro de instancia @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + constructores principales @@ -1994,7 +1994,7 @@ using type alias - using type alias + mediante alias de tipo @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + El operador ''&'' no debe usarse en parámetros o variables locales en métodos asincrónicos. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + El operador ''&'' no debe usarse en parámetros o variables locales en métodos asincrónicos. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + El parámetro '{0}' se captura en el estado del tipo envolvente y su valor también se pasa al constructor base. La clase base también puede capturar el valor. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + El parámetro se captura en el estado del tipo envolvente y su valor también se pasa al constructor base. La clase base también puede capturar el valor. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Un constructor declarado en un registro con una lista de parámetros debe tener el inicializador de constructor "this". + Un constructor declarado en un tipo con lista de parámetros debe tener un inicializador de constructor ''this''. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + El parámetro '{0}' no está leído. Parameter is unread. - Parameter is unread. + El parámetro no está leído. @@ -10381,22 +10381,22 @@ Considere la posibilidad de suprimir la advertencia solo si tiene la seguridad d The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + La cadena de versión especificada ''{0}'' no se ajusta al formato requerido: major[.minor[.build[.revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + La cadena de versión especificada ''{0}'' contiene caracteres comodín, que no son compatibles con el determinismo. Quite los caracteres comodín de la cadena de versión o deshabilite el determinismo para esta compilación. The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + La cadena de versión especificada ''{0}'' no se ajusta al formato requerido: major.minor.build.revision (sin caracteres comodín) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + La cadena de versión especificada ''{0}'' no se ajusta al formato recomendado: major.minor.build.revision diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index a9588016766f6..67db681971e65 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + L’identificateur '{0}' est ambiguë entre le type '{1}' et le paramètre '{2}' dans ce contexte. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Impossible d’utiliser le paramètre '{0}' qui a un type de référence similaire à une référence à l’intérieur d’une méthode anonyme, d’une expression lambda, d’une expression de requête ou d’une fonction locale. Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Les méthodes anonymes, les expressions lambda, les expressions de requête et les fonctions locales à l’intérieur d’une structure ne peuvent pas accéder au paramètre primaire du constructeur également utilisé à l’intérieur d’un membre de l’instance. Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Les méthodes anonymes, les expressions lambda, les expressions de requête et les fonctions locales dans un membre d’instance d’un struct ne peuvent pas accéder au paramètre du constructeur principal @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Un paramètre de constructeur primaire d’un type en lecture seule ne peut pas être assigné (sauf dans le setter init-only du type ou dans un initialisateur de variable). Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Les membres du paramètre du constructeur principal '{0}' d'un type en lecture seule ne peuvent pas être modifiés (sauf dans le setter de init-only du type ou dans l'initialiseur de variable). @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Un bras d’expression switch ne commence pas par un mot clé 'case'. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + L’utilisation de l’alias ne peut pas être un type référence Nullable. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Une ressource d’instruction d’utilisation de type '{0}' ne peut pas être utilisée dans des méthodes asynchrones ou des expressions lambda asynchrones. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + L’utilisation de l’alias ne peut pas être un type 'ref'. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + Le modificateur 'static' doit précéder le modificateur 'unsafe'. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Seul un 'using static' ou 'using alias' peut être 'unsafe'. @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + Une valeur constante de type '{0}' est attendue @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - L'utilisation d'un type de pointeur de fonction dans un 'typeof' au sein d'un attribut n'est pas prise en charge. + L’utilisation d’un type de pointeur de fonction dans ce contexte n’est pas prise en charge. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + Impossible d’utiliser le paramètre de constructeur principal '{0}' dans ce contexte. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Seule une déclaration partielle d'un seul enregistrement peut avoir une liste de paramètres + Seule une déclaration de type partiel d’un seul enregistrement peut avoir une liste de paramètres. @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Un constructeur déclaré dans un 'record struct' avec une liste de paramètres doit avoir un initialiseur 'this' qui appelle le constructeur principal ou un constructeur explicitement déclaré. + Un constructeur déclaré dans un 'struct' avec une liste de paramètres doit avoir un initialiseur 'this' qui appelle le constructeur principal ou un constructeur explicitement déclaré. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Un paramètre de constructeur primaire d’un type en lecture seule ne peut pas être utilisé comme valeur ref ou out (sauf dans le setter init-only du type ou dans un initialisateur de variable). Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Membres d’un paramètre de constructeur primaire '{0}' d’un type en lecture seule ne peut pas être utilisé comme valeur ref ou out (sauf dans le setter init-only du type ou dans un initialisateur de variable). @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Impossible de retourner le paramètre de constructeur principal '{0}' par référence. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Un paramètre de constructeur principal d’un type en lecture seule ne peuvent pas être retournés par une référence accessible en écriture Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Les membres du paramètre de constructeur principal '{0}' d’un type en lecture seule ne peuvent pas être retournés par une référence accessible en écriture @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + Le paramètre de constructeur principal struct '{0}' de type '{1}' provoque un cycle dans la disposition du struct @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Liste de paramètres inattendue. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}' est défini dans un module avec une version RefSafetyRulesAttribute non reconnue, '11' attendu. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Impossible d’utiliser le paramètre de constructeur principal '{0}' avec ref, out ou in à l’intérieur d’un membre d’instance. Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Nous n’avons pas pu utiliser le paramètre de constructeur principal '{0}' qui a un type de référence similaire à l’intérieur d’un membre d’instance @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + constructeurs principaux @@ -1994,7 +1994,7 @@ using type alias - using type alias + utilisation de l’alias de type @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + L’opérateur '&' ne doit pas être utilisé sur les paramètres ou les variables locales dans les méthodes asynchrones. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + L’opérateur '&' ne doit pas être utilisé sur les paramètres ou les variables locales dans les méthodes asynchrones. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Paramètre '{0}' est capturé dans l’état du type englobant et sa valeur est également passée au constructeur de base. La valeur peut également être capturée par la classe de base. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Un paramètre est capturé dans l’état du type englobant et sa valeur est également passée au constructeur de base. La valeur peut également être capturée par la classe de base. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Un constructeur déclaré dans un enregistrement avec une liste de paramètres doit avoir l'initialiseur de constructeur 'this'. + Un constructeur déclaré dans un type avec une liste de paramètres doit avoir 'this' initialisateur de constructeur. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + Paramètre '{0}' non lu. Parameter is unread. - Parameter is unread. + Paramètre non lu. @@ -10381,22 +10381,22 @@ Supprimez l'avertissement seulement si vous êtes sûr de ne pas vouloir attendr The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + La chaîne de version spécifiée '{0}' n’est pas conforme au format requis - major[.minor[.build[.revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + La chaîne de version spécifiée '{0}' contient des caractères génériques qui ne sont pas compatibles avec le déterminisme. Supprimez les caractères génériques de la chaîne de version ou désactivez le déterminisme pour cette compilation The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + La chaîne de version spécifiée '{0}' n’est pas conforme au format requis : major.minor.build.revision (sans caractères génériques) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + La chaîne de version spécifiée '{0}' n’est pas conforme au format recommandé : major.minor.build.revision diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 21a5f91e7a1a9..fb63a0510b8cb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + L'identificatore '{0}' è ambiguo tra il tipo '{1}' e il parametro '{2}'. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Non è possibile usare il parametro '{0}' con tipo simile a ref all'interno di un metodo anonimo, di un'espressione lambda, di un'espressione di query o di una funzione locale Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Metodi anonimi, espressioni lambda, espressioni di query e funzioni locali all'interno di uno struct non possono accedere al parametro del costruttore primario usato anche all'interno di un membro di istanza Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Metodi anonimi, espressioni lambda, espressioni di query e funzioni locali all'interno di un membro di istanza di uno struct non possono accedere al parametro del costruttore primario @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Non è assegnare un parametro del costruttore primario di un tipo di sola lettura, tranne che nel setter di sola inizializzazione del tipo o in un inizializzatore di variabile Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Non è possibile modificare i membri del parametro del costruttore primario '{0}' di un tipo di sola lettura, tranne che nel setter di sola inizializzazione del tipo o in un inizializzatore di variabile @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Un braccio dell'espressione switch non inizia con una parola chiave 'case'. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + L'alias using non può essere un tipo riferimento nullable. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Non è possibile usare una risorsa di istruzione using di tipo '{0}' in metodi asincroni o espressioni lambda asincrone. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + L'alias using non può essere di tipo 'ref'. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + Il modificatore 'static' deve precedere il modificatore 'unsafe'. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Solo 'using static' o 'using alias' può essere 'unsafe'. @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + È previsto un valore costante di tipo '{0}' @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - L'uso di un tipo di puntatore a funzione in un elemento 'typeof' di un attributo non è supportato. + L'uso di un tipo di puntatore a funzione in questo contesto non è supportato. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + Non è possibile usare il parametro del costruttore primario '{0}' in questo contesto. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Solo una dichiarazione parziale di singolo record può includere un elenco di parametri + Solo una dichiarazione parziale di singolo record può includere un elenco di parametri @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Un costruttore dichiarato in uno “struct di record” con elenco di parametri deve avere un inizializzatore “this” che chiama il costruttore primario o un costruttore dichiarato in modo esplicito. + Un costruttore dichiarato in uno “struct” con elenco di parametri deve avere un inizializzatore “this” che chiama il costruttore primario o un costruttore dichiarato in modo esplicito. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Non è possibile usare un parametro del costruttore primario come valore out o ref di un tipo di sola lettura, tranne che nel setter di sola inizializzazione del tipo o in un inizializzatore di variabile Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Non è possibile usare i membri del parametro del costruttore primario '{0}' come valore out o ref di un tipo di sola lettura, tranne che nel setter di sola inizializzazione del tipo o in un inizializzatore di variabile @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Non è possibile restituire il parametro del costruttore primario '{0}' per riferimento. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Un parametro del costruttore primario di un tipo di sola lettura non può essere restituito da un riferimento scrivibile Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + I membri del parametro del costruttore primario '{0}' di un tipo di sola lettura non possono essere restituiti da un riferimento scrivibile @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + Il parametro del costruttore primario struct '{0}' di tipo '{1}' causa un ciclo nel layout dello struct @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Elenco parametri imprevisto. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}' è definito in un modulo con una versione non riconosciuta di RefSafetyRulesAttribute. È previsto '11'. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Non è possibile usare il parametro ref, out o in del costruttore primario '{0}' all'interno di un membro di istanza Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Non è possibile usare il parametro del costruttore primario '{0}' con un tipo simile a ref all'interno di un membro di istanza @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + costruttori primari @@ -1994,7 +1994,7 @@ using type alias - using type alias + Alias di tipo using @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + L'operatore '&' non deve essere usato su parametri o variabili locali in metodi asincroni. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + L'operatore '&' non deve essere usato su parametri o variabili locali in metodi asincroni. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Il parametro '{0}' viene catturato nello stato del tipo di inclusione e il relativo valore viene passato anche al costruttore di base. Il valore potrebbe essere catturato anche dalla classe di base. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Il parametro viene catturato nello stato del tipo di inclusione e il relativo valore viene passato anche al costruttore di base. Il valore potrebbe essere catturato anche dalla classe di base. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Un costruttore dichiarato in un record con elenco di parametri deve includere l'inizializzatore di costruttore 'this'. + Un costruttore dichiarato in un record con elenco di parametri deve includere l'inizializzatore di costruttore 'this'. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + Il parametro '{0}' non è stato letto. Parameter is unread. - Parameter is unread. + Il parametro non è stato letto. @@ -10381,22 +10381,22 @@ Come procedura consigliata, è consigliabile attendere sempre la chiamata. The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + La stringa di versione specificata '{0}' non è conforme al formato richiesto: principale[.secondaria[.build[.revisione]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + La stringa di versione specificata '{0}' contiene caratteri jolly e questo non è compatibile con il determinismo. Rimuovere i caratteri jolly dalla stringa di versione o disabilitare il determinismo per questa compilazione The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + La stringa di versione specificata '{0}' non è conforme al formato richiesto: principale.secondaria.build.revisione (senza caratteri jolly) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + La stringa di versione specificata '{0}' non è conforme al formato consigliato: principale.secondaria.build.revisione diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 0af53a59263cb..27e5d1b44bd83 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + 識別子 '{0}' は、このコンテキストの型 '{1}' とパラメーター '{2}' の間であいまいです。 @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + 匿名メソッド、ラムダ式、クエリ式、またはローカル関数内で ref に似た型を持つパラメーター '{0}' を使用することはできません Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + 構造体内の匿名メソッド、ラムダ式、クエリ式、ローカル関数は、インスタンス メンバー内でも使用されるプライマリ コンストラクター パラメーターにアクセスできません Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + 構造体のインスタンス メンバー内の匿名メソッド、ラムダ式、クエリ式、ローカル関数は、プライマリ コンストラクター パラメーターにアクセスできません @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + 読み取り専用型のプライマリ コンストラクター パラメーターを割り当てることはできません (型または変数初期化子の init 専用セッターを除く)。 Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + 読み取り専用型のプライマリ コンストラクター パラメーター '{0}' のメンバーは変更できません (型または変数初期化子の init 専用セッターを除く) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + switch 式の arm が 'case' キーワードで始まりません。 @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + Using エイリアスを NULL 許容参照型にすることはできません。 @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + 型 '{0}' の using ステートメント リソースは、非同期メソッドまたは非同期ラムダ式では使用できません。 Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + using エイリアスを 'ref' 型にすることはできません。 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + 'static' 修飾子は 'unsafe' 修飾子の前に指定する必要があります。 @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + 'unsafe' に設定できるのは、'using static' または 'using エイリアス' のみです。 @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - 属性内の 'typeof' で関数ポインター型を使用することはサポートされていません。 + このコンテキストでの関数ポインター型の使用はサポートされていません。 @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + このコンテキストでは、プライマリ コンストラクター パラメーター '{0}' を使用できません。 @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - 1 つのレコードの部分宣言のみがパラメーター リストを持つことができます + 単一の部分型宣言のみがパラメーター リストを持つことができます @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - パラメーター リストを含む "record struct" で宣言されたコンストラクターには、プライマリ コンストラクターまたは明示的に宣言されたコンストラクターを呼び出す "this" 初期化子が必要です。 + パラメーター リストを使用して 'struct' で宣言されたコンストラクターには、プライマリ コンストラクターまたは明示的に宣言されたコンストラクターを呼び出す 'this' 初期化子が必要です。 @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 読み取り専用型のプライマリ コンストラクター パラメーターは、ref または out 値として使用できません (型または変数初期化子の init 専用セッターを除く)。 Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 読み取り専用型のプライマリ コンストラクター パラメーター '{0}' のメンバーを ref または out 値として使用することはできません (型または変数初期化子の init 専用セッターを除く)。 @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + 参照渡しでプライマリ コンストラクター パラメーター '{0}' を返すことはできません。 A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + 読み取り専用型のプライマリ コンストラクター パラメーターを書き込み可能な参照で返すことはできません Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + 読み取り専用型のプライマリ コンストラクター パラメーター '{0}' のメンバーを書き込み可能な参照で返すことはできません @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + 型 '{1}' の構造体のプライマリ コンストラクター パラメーター '{0}' により、構造体レイアウトで循環が発生します @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + 予期しないパラメーター リストです。 @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}' は、認識されない RefSafetyRulesAttribute バージョンを持つモジュールで定義され、'11' が必要です。 @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + インスタンス メンバー内のプライマリ コンストラクター パラメーター '{0}' では ref、out、in を使用できません Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + インスタンス メンバー内に ref に似た型を持つプライマリ コンストラクター パラメーター '{0}' を使用することはできません @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + プライマリ コンストラクター @@ -1994,7 +1994,7 @@ using type alias - using type alias + using 型のエイリアス @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 演算子は、非同期メソッドのパラメーターまたはローカル変数では使用できません。 The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 演算子は、非同期メソッドのパラメーターまたはローカル変数では使用できません。 @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + パラメーター '{0}' は外側の型の状態にキャプチャされ、その値も基底コンストラクターに渡されます。この値は、基底クラスでもキャプチャされる可能性があります。 Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + パラメーターは外側の型の状態にキャプチャされ、その値も基底コンストラクターに渡されます。この値は、基底クラスでもキャプチャされる可能性があります。 @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - パラメーター リストを含むレコード内で宣言されたコンストラクターには、'this' コンストラクター初期化子が必要です。 + パラメーター リストを持つ型で宣言されたコンストラクターには、'this' コンストラクター初期化子が必要です。 @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + パラメーター '{0}' は未読です。 Parameter is unread. - Parameter is unread. + パラメーターが未読です。 @@ -7812,7 +7812,7 @@ If such a class is used as a base class and if the deriving class defines a dest A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException. - 前の catch 句は、すべての例外を既にキャッチしています。スローされる例外以外のものはすべて System.Runtime.CompilerServices.RuntimeWrappedException に折り返saます。 + 前の catch 句は、すべての例外を既にキャッチしています。スローされる例外以外のものはすべて System.Runtime.CompilerServices.RuntimeWrappedException にラップされます。 @@ -10381,22 +10381,22 @@ You should consider suppressing the warning only if you're sure that you don't w The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + 指定したバージョン文字列 '{0}' は、必要な形式 (major[.minor[.build[.revision]]]) に従っていません。 The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + 指定されたバージョン文字列 '{0}' には、決定性と互換性のないワイルドカードが含まれています。バージョン文字列からワイルドカードを削除するか、このコンパイルの決定性を無効にしてください。 The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + 指定したバージョン文字列 '{0}' は、必要な形式 (major.minor.build.revision、ワイルドカードなし) に従っていません。 The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + 指定したバージョン文字列 '{0}' は、推奨される形式 (major.minor.build.revision) に従っていません diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 394bc1f915d4e..f664e56cd4e90 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + '{0}' 식별자는 이 컨텍스트에서 '{1}' 형식과 '{2}' 매개 변수 사이에 모호합니다. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + 무명 메서드, 람다 식, 쿼리 식 또는 로컬 함수 내에 ref 유사 형식이 있는 '{0}' 매개 변수를 사용할 수 없습니다. Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + 익명 메서드, 람다 식, 쿼리 식 및 구조체 내의 로컬 함수는 인스턴스 멤버 내에서도 사용되는 기본 생성자 매개 변수에 액세스할 수 없습니다. Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + 구조체의 인스턴스 멤버 내에 있는 무명 메서드, 람다 식, 쿼리 식 및 로컬 함수는 기본 생성자 매개 변수에 액세스할 수 없습니다. @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + 읽기 전용 형식의 기본 생성자 매개 변수는 할당할 수 없습니다(형식의 init 전용 setter 또는 변수 이니셜라이저 제외). Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + 읽기 전용 형식의 기본 생성자 매개 변수 '{0}'의 멤버는 수정할 수 없습니다(형식의 init 전용 setter 또는 변수 이니셜라이저 제외). @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + 스위치 식 arm은 'case' 키워드로 시작하지 않습니다. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + 별칭 사용은 nullable 참조 형식일 수 없습니다. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + '{0}' 형식의 using 문 리소스는 비동기 메서드 또는 비동기 람다 식에 사용할 수 없습니다. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + 별칭을 사용하는 것은 'ref' 유형일 수 없습니다. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + 'static' 한정자는 'unsafe' 한정자 앞에 와야 합니다. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + 'using static' 또는 'using alias'만 'unsafe'일 수 있습니다. @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - 특성의 'typeof'에 함수 포인터 형식을 사용할 수 없습니다. + 이 컨텍스트에서 함수 포인터 형식을 사용하는 것은 지원되지 않습니다. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + 이 컨텍스트에서는 기본 생성자 '{0}' 매개 변수를 사용할 수 없습니다. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - 단일 레코드 partial 선언에만 매개 변수 목록을 사용할 수 있습니다. + 단일 부분 형식 선언만 매개 변수 목록을 가질 수 있습니다. @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - 매개 변수 목록을 사용하여 '레코드 구조체'에 선언된 생성자에는 기본 생성자 또는 명시적으로 선언된 생성자를 호출하는 'this' 이니셜라이저가 있어야 합니다. + 매개 변수 목록을 사용하여 'struct'에 선언된 생성자에는 기본 생성자 또는 명시적으로 선언된 생성자를 호출하는 'this' 이니셜라이저가 있어야 합니다. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 읽기 전용 형식의 기본 생성자 매개 변수는 ref 또는 out 값으로 사용할 수 없습니다(형식의 init 전용 setter 또는 변수 이니셜라이저 제외). Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 읽기 전용 형식의 기본 생성자 '{0}' 매개 변수의 멤버는 ref 또는 out 값으로 사용할 수 없습니다(형식의 init 전용 setter 또는 변수 이니셜라이저 제외). @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + 참조로 기본 생성자 '{0}’ 매개 변수를 반환할 수 없습니다. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + 읽기 전용 형식의 기본 생성자 매개 변수는 쓰기 가능 참조로 반환할 수 없습니다. Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + 읽기 전용 형식의 기본 생성자 '{0}' 매개 변수 의 멤버는 쓰기 가능 참조로 반환할 수 없습니다. @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + '{1}' 형식의 구조체 기본 생성자 '{0}' 매개 변수로 인해 구조체 레이아웃의 주기가 발생합니다. @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + 예기치 않은 매개 변수 목록입니다. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}'은(는) 인식할 수 없는 RefSafetyRulesAttribute 버전이 있는 모듈에 정의되어 있으며 '11'이 필요합니다. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + 인스턴스 멤버 내에서 ref, out 또는 기본 생성자 '{0}' 매개 변수를 사용할 수 없습니다. Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + 인스턴스 멤버 내에 ref 유사 형식이 있는 기본 생성자 '{0}' 매개 변수를 사용할 수 없습니다. @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + 기본 생성자 @@ -1994,7 +1994,7 @@ using type alias - using type alias + 유형 별칭 사용 @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 연산자는 비동기 메서드의 매개 변수 또는 지역 변수에 사용하면 안 됩니다. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 연산자는 비동기 메서드의 매개 변수 또는 지역 변수에 사용하면 안 됩니다. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + '{0}' 매개 변수는 둘러싸인 형식의 상태로 캡처되며 해당 값도 기본 생성자에 전달됩니다. 기본 클래스에서도 값을 캡처할 수 있습니다. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + 매개 변수는 둘러싸인 형식의 상태로 캡처되며 해당 값도 기본 생성자에 전달됩니다. 기본 클래스에서도 값을 캡처할 수 있습니다. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - 매개 변수 목록이 있는 레코드에 선언된 생성자에는 'this' 생성자 이니셜라이저가 있어야 합니다. + 매개 변수 목록이 있는 형식에서 선언된 생성자에는 'this' 생성자 이니셜라이저가 있어야 합니다. @@ -4432,12 +4432,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + ‘{0}’ 매개 변수를 읽지 않았습니다. Parameter is unread. - Parameter is unread. + 매개 변수를 읽지 않았습니다. @@ -10380,22 +10380,22 @@ You should consider suppressing the warning only if you're sure that you don't w The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + 지정한 버전 문자열 '{0}'이(가) 필요한 형식 major[.minor[.build[.revision]]]을 따르지 않습니다. The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + 지정한 버전 문자열 '{0}'에는 결정성과 호환되지 않는 와일드카드가 포함되어 있습니다. 버전 문자열에서 와일드카드를 제거하거나 이 컴파일에 대해 결정성을 사용하지 않도록 설정하세요. The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + 지정한 버전 문자열 '{0}'이(가) 필요한 형식 major.minor.build.revision(와일드카드 없음)을 따르지 않습니다. The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + 지정한 버전 문자열 '{0}'이(가) 권장 형식 major.minor.build.revision을 따르지 않습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3e6d3de90b2ae..cb357acaa7421 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + Identyfikator '{0}' jest niejednoznaczny między typem '{1}' i parametrem '{2}' w tym kontekście. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Nie można użyć parametru '{0}', który ma typ przypominający odwołanie wewnątrz metody anonimowej, wyrażenia lambda, wyrażenia zapytania lub funkcji lokalnej Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Metody anonimowe, wyrażenia lambda, wyrażenia zapytań i funkcje lokalne wewnątrz struktury nie mogą uzyskać dostępu do głównego parametru konstruktora używanego również wewnątrz członka wystąpienia. Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Metody anonimowe, wyrażenia lambda, wyrażenia zapytań i funkcje lokalne wewnątrz członka instancji struktury nie mają dostępu do głównego parametru konstruktora. @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Podstawowy parametr konstruktora typu tylko do odczytu nie może być przypisany (z wyjątkiem setera inicjującego typu lub inicjalizatora zmiennej) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Elementy podstawowego parametru konstruktora '{0}' typu tylko do odczytu nie mogą być modyfikowane (z wyjątkiem inicjującego settera typu lub inicjalizatora zmiennej) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Ramię wyrażenia przełączające nie rozpoczyna się od słowa kluczowego „case”. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + Używanie aliasu nie może być typem referencyjnym dopuszczającym wartość null. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Zasobu instrukcji przy użyciu typu '{0}' nie można używać w metodach asynchronicznych ani asynchronicznych wyrażeniach lambda. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + Używanie aliasu nie może być typem „ref”. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + Modyfikator „statyczny” musi poprzedzać modyfikator „niebezpieczny”. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Tylko element „użycie statyczne” lub „użycie aliasu” może być „niebezpieczne”. @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - Użycie typu wskaźnika funkcji w elemencie „typeof” w atrybucie nie jest obsługiwane. + Używanie typu wskaźnika funkcji w tym kontekście nie jest obsługiwane. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + W tym kontekście nie można użyć podstawowego parametru konstruktora '{0}'. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Tylko pojedyncza częściowa deklaracja rekordu może mieć listę parametrów + Tylko pojedyncza deklaracja typu częściowego może mieć listę parametrów @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Konstruktor zadeklarowany w „strukturze rekordów” z listą parametrów musi mieć inicjator „this”, który wywołuje konstruktor podstawowy lub jawnie zadeklarowany konstruktor. + Konstruktor zadeklarowany w „strukturze rekordów” z listą parametrów musi mieć inicjator „this”, który wywołuje konstruktor podstawowy lub jawnie zadeklarowany konstruktor. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Podstawowy parametr konstruktora typu tylko do odczytu nie może być użyty jako wartość ref lub out (z wyjątkiem inicjującego settera typu lub inicjalizatora zmiennej) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Składowych podstawowego parametru konstruktora '{0}' typu tylko do odczytu nie można używać jako wartości ref ani out (z wyjątkiem inicjującego settera typu lub inicjalizatora zmiennej) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Nie można zwrócić podstawowego parametru konstruktora '{0}' przez odwołanie. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Podstawowy parametr konstruktora typu tylko do odczytu nie może być zwracany przez zapisywalne odwołanie Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Składowe podstawowego parametru konstruktora '{0}' typu tylko do odczytu nie mogą być zwracane przez zapisywalne odwołanie @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + Podstawowy parametr konstruktora struktury '{0}' typu '{1}' powoduje cykl w układzie struktury @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Nieoczekiwana lista parametrów. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + Element '{0}' jest zdefiniowany w module z nierozpoznaną wersją RefSafetyRulesAttribute, oczekiwano „11”. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Nie można użyć ref, out lub w podstawowym parametrze konstruktora '{0}' wewnątrz elementu członkowskiego wystąpienia Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Nie można użyć podstawowego parametru konstruktora '{0}', który ma typ przypominający odwołanie wewnątrz składowej wystąpienia @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + konstruktory podstawowe @@ -1994,7 +1994,7 @@ using type alias - using type alias + przy użyciu aliasu typu @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Operator „&” nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Operator „&” nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Parametr '{0}' jest przechwytywane do stanu otaczającego typu, a jego wartość jest również przekazywana do konstruktora podstawowego. Wartość może zostać również przechwycona przez klasę bazową. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Parametr zostaje przechwycony do stanu otaczającego typu, a jego wartość jest również przekazywana do konstruktora podstawowego. Wartość może być również przechwycona przez klasę bazową. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Konstruktor zadeklarowany w rekordzie z listą parametrów musi mieć inicjator konstruktora „this”. + Konstruktor zadeklarowany w typie z listą parametrów musi mieć „ten” inicjalizator konstruktora. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + Parametr '{0}' jest nieodczytany. Parameter is unread. - Parameter is unread. + Parametr jest nieodczytany. @@ -10381,22 +10381,22 @@ Pominięcie ostrzeżenia należy wziąć pod uwagę tylko w sytuacji, gdy na pew The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + Określony ciąg wersji „{0}” jest niezgodny z wymaganym formatem — major[.minor[.build[.revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + Określony ciąg wersji „{0}” zawiera znaki wieloznaczne, które nie są zgodne z determinizmem. Usuń znaki wieloznaczne z ciągu wersji lub wyłącz determinizm dla tej kompilacji The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + Określony ciąg wersji „{0}” nie jest zgodny z wymaganym formatem — major.minor.build.revision (bez znaków wieloznacznych) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + Określony ciąg wersji „{0}” nie jest zgodny z zalecanym formatem — major.minor.build.revision diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index fd7a404d7cbcb..86157d7e48af3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + O identificador "{0}" é ambíguo entre o tipo "{1}" e o parâmetro "{2}" neste contexto. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Não é possível usar o parâmetro "{0}" que tenha o tipo ref-like dentro de um método anônimo, expressão lambda, expressão de consulta ou função local Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Métodos anônimos, expressões lambda, expressões de consulta e funções locais dentro de um struct não podem acessar o parâmetro de construtor primário também usado dentro de um membro de instância Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Métodos anônimos, expressões lambda, expressões de consulta e funções locais dentro de um membro de instância de um struct não podem acessar o parâmetro do construtor primário @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Um parâmetro de construtor primário de um tipo somente leitura não pode ser atribuído (exceto no setter somente inicialização do tipo ou em um inicializador de variável) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Os membros do parâmetro de construtor primário "{0}" de um tipo somente leitura não podem ser modificados (exceto no setter somente inicializador init do tipo ou em um inicializador de variável) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + Um braço de expressão alternar não começa com uma palavra-chave 'case'. @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + O uso de alias não pode ser um tipo de referência anulável. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Um recurso de instrução using do tipo "{0}" não pode ser usado em métodos assíncronos ou expressões lambda assíncronas. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + O uso de alias não pode ser do tipo 'ref'. 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + O modificador 'estático' deve preceder o modificador 'inseguro'. @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Somente um 'usando estático' ou 'usando alias' pode ser 'inseguro'. @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - Não há suporte para o uso de um tipo de ponteiro de função em um 'typeof' em um atributo. + Não há suporte para o uso de um tipo de ponteiro de função neste contexto. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + Não é possível usar o parâmetro de construtor primário "{0}" neste contexto. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Apenas uma declaração parcial de registro único pode ter uma lista de parâmetros + Apenas uma declaração de tipo parcial simples pode ter uma lista de parâmetros @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Um construtor declarado em uma 'estrutura de registro' com lista de parâmetros deve ter um inicializador 'este' que chama o construtor primário ou um construtor declarado explicitamente. + Um construtor declarado em um "struct" com lista de parâmetros deve ter um inicializador "this" que chama o construtor primário ou um construtor explicitamente declarado. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Um parâmetro de construtor primário de um tipo somente leitura não pode ser usado como um valor ref ou out (exceto no setter somente inicialização do tipo ou em um inicializador de variável) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Os membros do parâmetro de construtor primário "{0}" de um tipo somente leitura não podem ser usados como um valor ref ou out (exceto no setter somente inicialização do tipo ou em um inicializador de variável) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Não é possível retornar o parâmetro de construtor primário "{0}" por referência. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Um parâmetro de construtor primário de um tipo somente leitura não pode ser retornado por referência gravável Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Os membros do parâmetro de construtor primário "{0}" de um tipo somente leitura não podem ser retornados por referência gravável @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + O parâmetro do construtor primário struct "{0}" do tipo "{1}" causa um ciclo no layout do struct @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Lista de parâmetros inesperada. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + "{0}" é definido em um módulo com uma versão RefSafetyRulesAttribute não reconhecida, esperando "11". @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Não é possível usar ref, out ou no parâmetro de construtor primário "{0}" dentro de um membro da instância Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Não é possível usar o parâmetro de construtor primário "{0}" que tem o tipo ref-like dentro de um membro de instância @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + construtores primários @@ -1994,7 +1994,7 @@ using type alias - using type alias + usando tipo alias @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + O operador '&' não deve ser usado em parâmetros ou variáveis locais em métodos assíncronos. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + O operador '&' não deve ser usado em parâmetros ou variáveis locais em métodos assíncronos. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + O parâmetro "{0}" é capturado no estado do tipo delimitador e seu valor também é passado para o construtor base. O valor também pode ser capturado pela classe base. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + O parâmetro é capturado no estado do tipo delimitador e seu valor também é passado para o construtor base. O valor também pode ser capturado pela classe base. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Um construtor declarado em um registro com a lista de parâmetros precisa ter o inicializador de construtor 'this'. + Um construtor declarado em um tipo com uma lista de parâmetros deve ter o inicializador de construtor 'this'. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + O parâmetro "{0}" não está lido. Parameter is unread. - Parameter is unread. + O parâmetro não está lido. @@ -10381,22 +10381,22 @@ Você pode suprimir o aviso se tiver certeza de que não vai querer aguardar a c The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + A cadeia de caracteres de versão especificada '{0}' não está de acordo com o formato requerido - major[.minor[.build[.revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + A cadeia de caracteres de versão especificada '{0}' contém curingas, que não são compatíveis com o determinismo. Remova os curingas da cadeia de caracteres da versão ou desative o determinismo para esta compilação The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + A cadeia de caracteres de versão especificada '{0}' não está em conformidade com o formato necessário - major.minor.build.revision (sem curingas) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + A cadeia de caracteres de versão especificada '{0}' não está em conformidade com o formato recomendado - major.minor.build.revision diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index d613ae8c16b44..1ef0d19b1ac13 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + Идентификатор "{0}" является неоднозначным между типом "{1}" и параметром "{2}" в этом контексте. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Невозможно использовать параметр "{0}" типа ref-like внутри анонимного метода, лямбда-выражения, выражения запроса или локальной функции Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Анонимные методы, лямбда-выражения, выражения запроса и локальные функции внутри структуры не могут получить доступ к параметру основного конструктора, также используемому внутри элемента экземпляра Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Анонимные методы, лямбда-выражения, выражения запроса и локальные функции внутри элемента экземпляра структуры не могут получить доступ к параметру основного конструктора @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Параметр основного конструктора типа, доступного только для чтения, нельзя использовать в назначении (за исключением метода задания с типом, предназначенным только для инициализации, или инициализатора переменной) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Элементы параметра основного конструктора "{0}" типа, доступного только для чтения, нельзя изменить (за исключением метода задания с типом, предназначенным только для инициализации, или инициализатора переменной) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + ARM выражения переключателя не начинается с ключевого слова "case". @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + Параметр использования псевдонима не может быть ссылочным типом, допускающим значение NULL. @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + Ресурс оператора использования типа "{0}" нельзя применять в асинхронных методах или асинхронных лямбда-выражениях. Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + Параметр использования псевдонима не может быть типом "ref". 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + Модификатор "static" должен предшествовать модификатору "unsafe". @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + Только параметр "using static" или "using alias" может иметь значение "unsafe". @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + Ожидается значение константы типа "{0}" @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - Использование типа указателя на функцию в "typeof" атрибута не поддерживается. + Использование типа указателя функции в этом контексте не поддерживается. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + Невозможно использовать параметр основного конструктора "{0}" в этом контексте. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Только частичное объявление отдельной записи может иметь список параметров. + Только отдельное объявление разделяемого типа может содержать список параметров @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Конструктор, объявленный в "record struct" со списком параметров, должен содержать инициализатор "this", который вызывает первичный конструктор или явно объявленный конструктор. + Конструктор, объявленный в "struct" со списком параметров, должен содержать инициализатор "this", вызывающий основной конструктор или явно объявленный конструктор. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Параметр основного конструктора типа, доступного только для чтения, нельзя использовать как значение ref или out (за исключением метода задания с типом, предназначенным только для инициализации, или инициализатора переменной) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Элементы параметра основного конструктора "{0}" типа, доступного только для чтения, нельзя использовать как значение ref или out (за исключением метода задания с типом, предназначенным только для инициализации, или инициализатора переменной) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + Невозможно вернуть параметр основного конструктора "{0}" с помощью ссылки. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Параметр основного конструктора типа, доступного только для чтения, нельзя вернуть с помощью записываемой ссылки Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Элементы параметра основного конструктора "{0}" типа, доступного только для чтения, нельзя вернуть с помощью записываемой ссылки @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + Параметр основного конструктора структуры "{0}" типа "{1}" вызывает цикл в макете структуры @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Неожиданный список параметров. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + "{0}" определен в модуле с нераспознанной версией RefSafetyRulesAttribute. Ожидается "11". @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Невозможно использовать параметр основного конструктора "{0}" с модификаторами ref, out или in внутри элемента экземпляра Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Невозможно использовать параметр основного конструктора "{0}" типа ref-like внутри элемента экземпляра @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + основные конструкторы @@ -1994,7 +1994,7 @@ using type alias - using type alias + использование псевдонима типа @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Оператор "&" не следует использовать для параметров или локальных переменных в асинхронных методах. The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + Оператор "&" не следует использовать для параметров или локальных переменных в асинхронных методах. @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Параметр "{0}" записан в состоянии включающего типа, а его значение также передается базовому конструктору. Значение также может быть записано базовым классом. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Параметр записан в состоянии включающего типа, а его значение также передается базовому конструктору. Значение также может быть записано базовым классом. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Конструктор, объявленный в записи со списком параметров, должен иметь инициализатор конструктора "this". + Конструктор, объявленный в типе со списком параметров, должен содержать инициализатор конструктора "this". @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + Параметр "{0}" не прочитан. Parameter is unread. - Parameter is unread. + Параметр не прочитан. @@ -10381,22 +10381,22 @@ You should consider suppressing the warning only if you're sure that you don't w The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + Указанная строка версии "{0}" не соответствует требуемому формату: основной номер[.дополнительный номер[.сборка[.редакция]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + Указанная строка версии "{0}" содержит подстановочные знаки, которые несовместимы с детерминизмом. Удалите подстановочные знаки из строки версии или отключите детерминизм для этой компиляции The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + Указанная строка версии "{0}" не соответствует требуемому формату: основной номер.дополнительный номер.сборка.редакция (без подстановочных знаков) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + Указанная строка версии "{0}" не соответствует рекомендованному формату: основной номер.дополнительный номер.сборка.редакция diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index f635159e42b4d..52da2149a2e34 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + Bu bağlamda '{0}' tanımlayıcısı, '{1}' tipi ve '{2}' parametresi arasında belirsizdir. @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + Anonim bir yöntem, lambda ifadesi, sorgu ifadesi veya yerel işlev içinde ref benzeri türe sahip '{0}' parametresi kullanılamaz Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + Bir yapı içindeki anonim metotlar, lambda ifadeleri, sorgu ifadeleri ve yerel işlevler, bir örnek üye içinde de kullanılan birincil oluşturucu parametresine erişemez Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + Bir yapının örnek üyesi içindeki anonim metotlar, lambda ifadeleri, sorgu ifadeleri ve yerel işlevler, birincil oluşturucu parametresine erişemez @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + Salt okunur bir türün birincil oluşturucu parametresi atanamaz (türün yalnızca init ayarlayıcısı veya bir değişken başlatıcısı dışında) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + Salt okunur bir türün '{0}' birincil oluşturucu parametresinin üyeleri değiştirilemez (türün yalnızca init ayarlayıcısı veya bir değişken başlatıcısı dışında) @@ -264,7 +264,7 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + '{0}' türündeki bir using deyimi kaynağı, asenkron yöntemlerde veya asenkron lambda ifadelerinde kullanılamaz. @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + '{0}' türünde bir sabit değer bekleniyor @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - Öznitelikte bir 'typeof' içinde işlev işaretçisi türü kullanılması desteklenmez. + Bu bağlamda bir işlev işaretçisi türünün kullanılması desteklenmez. @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + Bu bağlamda '{0}' birincil oluşturucu parametresi kullanılamaz. @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - Yalnızca tek kaydın kısmi bildiriminde parametre listesi olabilir + Yalnızca tek bir parçalı tür bildiriminde bir parametre listesi olabilir @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - Parametre listesiyle bir “kayıt yapısı”nda bildirilen bir oluşturucu, birincil oluşturucuyu veya açıkça bildirilen bir oluşturucuyu çağıran bir “this” başlatıcısına sahip olmalıdır. + Parametre listesiyle bir 'struct' içinde bildirilen bir oluşturucunun, birincil oluşturucuyu veya açıkça bildirilmiş bir oluşturucuyu çağıran bir 'this' başlatıcısı olmalıdır. @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Salt okunur bir türün birincil oluşturucu parametresi, bir ref veya out değeri olarak kullanılamaz (türün yalnızca init ayarlayıcısı veya bir değişken başlatıcısı dışında) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + Salt okunur bir türün '{0}' birincil oluşturucu parametresinin üyeleri, bir ref veya out değeri olarak kullanılamaz (türün yalnızca init ayarlayıcısı veya bir değişken başlatıcı dışında) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + '{0}' birincil oluşturucu parametresi referans olarak döndürülemez. A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + Salt okunur bir türdeki birincil oluşturucu parametresi, yazılabilir referans tarafından döndürülemez Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + Salt okunur bir türün '{0}' birincil oluşturucu parametresinin üyeleri, yazılabilir referans tarafından döndürülemez @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + '{1}' tipindeki '{0}' yapı birincil oluşturucu parametresi, yapı düzeninde bir döngüye neden olur @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + Beklenmeyen parametre listesi. @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}' tanınmayan bir RefSafetyRulesAttribute sürümüne sahip bir modülde tanımlandı ve '11' bekleniyor. @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + Bir örnek üye içinde ref, out veya in '{0}' birincil oluşturucu parametresi kullanılamaz Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + Bir örnek üye içinde ref benzeri türe sahip '{0}' birincil oluşturucu parametresi kullanılamaz @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + birincil oluşturucular @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + '{0}' parametresi kapsayan türün durumuna yakalandı ve değeri temel oluşturucuya da geçirildi. Değer, temel sınıf tarafından da yakalanamıyor olabilir. Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + Parametre, çevreleyen türün durumunda yakalanır ve değeri de temel oluşturucuya iletilir. Değer, temel sınıf tarafından da yakalanabilir. @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - Parametre listesi içeren bir kayıtta bildirilen bir oluşturucu, 'this' oluşturucu başlatıcısına sahip olmalıdır. + Parametre listesine sahip bir türde bildirilmiş bir oluşturucu, 'this' oluşturucu başlatıcıya sahip olmalıdır. @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + '{0}' parametresi okunmamış. Parameter is unread. - Parameter is unread. + Parametre okunmamış. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 25c21dfb1ae4a..cefa521ea09ed 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + 在此上下文中,标识符“{0}”在类型“{1}”和参数“{2}”之间不明确。 @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + 无法使用匿名方法、lambda 表达式、查询表达式或局部函数内具有 ref-like 类型的参数“{0}” Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + 结构内的匿名方法、lambda 表达式、查询表达式和局部函数无法访问同时在实例成员内使用的主构造函数参数 Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + 结构的实例成员内的匿名方法、lambda 表达式、查询表达式和局部函数无法访问主构造函数参数 @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + 无法将只读类型的主构造函数参数分配给(在该类型的 init-only 设定子或变量初始值设定项中除外) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + 无法修改只读类型的主构造函数参数“{0}”的成员(在该类型的 init-only 设定子或变量初始值设定项中除外) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + 切换表达式 arm 不以 “case” 关键字 (keyword)开头。 @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + 使用别名不能为可为 null 的引用类型。 @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + 无法在异步方法或异步 lambda 表达式中使用类型为“{0}”的 using 语句资源。 Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + 使用别名不能是 “ref” 类型。 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + 'static' 修饰符必须位于 'unsafe' 修饰符之前。 @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + 只有 “using static” 或 “using alias” 才能为 “unsafe”。 @@ -409,7 +409,7 @@ A constant value of type '{0}' is expected - A constant value of type '{0}' is expected + 应为 '{0}' 类型的常量值 @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - 不支持在属性中使用 "typeof" 函数指针类型。 + 不支持在此上下文中使用函数指针类型。 @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + 无法在此上下文中使用主构造函数参数“{0}”。 @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - 只有一个记录分部声明可以具有参数列表 + 只有一个分部类型声明可以拥有参数列表 @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - 在带有参数列表的 "record struct" 中声明的构造函数必须具有调用主构造函数或显式声明的构造函数的 "this" 初始值设定项。 + 在带有参数列表的“struct”中声明的构造函数必须具有调用主构造函数或显式声明的构造函数的“this”初始化表达式。 @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 只读类型的主构造函数参数不能用作 ref 或 out 值(在该类型的 init-only 设定子或变量初始值设定项中除外) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 只读类型的主构造函数参数“{0}”的成员不能用作 ref 或 out 值(在该类型的 init-only 设定子或变量初始值设定项中除外) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + 无法按引用返回主构造函数参数“{0}”。 A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + 可写引用无法返回只读类型的主构造函数参数 Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + 可写引用无法返回只读类型的主构造函数参数“{0}”的成员 @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + 类型为“{1}”的结构主构造函数参数“{0}”导致结构布局中出现循环 @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + 意外的参数列表。 @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + “{0}”在具有无法识别的 RefSafetyRulesAttribute 版本(应为“11”)的模块中定义。 @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + 无法在实例成员内的主构造函数参数 “{0}” 中使用 ref、out 或 Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + 无法使用实例成员内具有 ref-like 类型的主构造函数参数 “{0}” @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + 主构造函数 @@ -1994,7 +1994,7 @@ using type alias - using type alias + 使用类型别名 @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 运算符不应用于异步方法中的参数或局部变量。 The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 运算符不应用于异步方法中的参数或局部变量。 @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + 参数“{0}”捕获到封闭类型状态,其值也传递给基构造函数。该值也可能由基类捕获。 Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + 参数捕获到封闭类型状态,其值也传递给基构造函数。该值也可能由基类捕获。 @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - 在带参数列表的记录中声明的构造函数必须具有 "this" 构造函数初始值设定项。 + 在带参数列表的类型中声明的构造函数必须拥有“this”构造函数初始化表达式。 @@ -4438,12 +4438,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + 参数“{0}”未读。 Parameter is unread. - Parameter is unread. + 参数未读。 @@ -10386,22 +10386,22 @@ You should consider suppressing the warning only if you're sure that you don't w The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + 指定版本字符串 '{0}' 不符合所需格式 - major[.minor[.build[.revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + 指定的版本字符串 '{0}' 包含通配符,这与确定性不兼容。请删除版本字符串中的通配符,或禁用此编译的确定性。 The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + 指定的版本字符串 '{0}' 不符合所需格式 - major.minor.build.revision (不带通配符) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + 指定版本字符串 '{0}' 不符合建议格式 - major.minor.build.revision diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 47bd959f2b860..551edd0bf56ef 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -59,7 +59,7 @@ Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. - Identifier '{0}' is ambiguous between type '{1}' and parameter '{2}' in this context. + 在此內容中,類型 '{1}' 與參數 '{2}' 之間的識別碼 '{0}' 不明確。 @@ -69,17 +69,17 @@ Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function - Cannot use parameter '{0}' that has ref-like type inside an anonymous method, lambda expression, query expression, or local function + 無法使用在匿名方法、Lambda 運算式、查詢運算式或區域函式內具有類似參考類型的參數 '{0}' Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member - Anonymous methods, lambda expressions, query expressions, and local functions inside a struct cannot access primary constructor parameter also used inside an instance member + 結構內的匿名方法、Lambda 運算式、查詢運算式和區域函式無法存取也在執行個體成員內使用的主要建構函式參數 Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter - Anonymous methods, lambda expressions, query expressions, and local functions inside an instance member of a struct cannot access primary constructor parameter + 結構的執行個體成員內的匿名方法、Lambda 運算式、查詢運算式和區域函式無法存取主要建構函式參數 @@ -94,12 +94,12 @@ A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be assigned to (except in init-only setter of the type or a variable initializer) + 無法指派唯讀類型的主要建構函式參數 (類型的 init-only setter 或變數初始設定式中除外) Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be modified (except in init-only setter of the type or a variable initializer) + 無法修改唯讀類型的主要建構函式參數 '{0}' 的成員 (類型的 init-only setter 或變數初始設定式中除外) @@ -194,7 +194,7 @@ A switch expression arm does not begin with a 'case' keyword. - A switch expression arm does not begin with a 'case' keyword. + 切換運算式 ARM 不會以 'case' 關鍵字開頭。 @@ -234,7 +234,7 @@ Using alias cannot be a nullable reference type. - Using alias cannot be a nullable reference type. + 使用別名不可以是可為 Null 的參考型別。 @@ -264,17 +264,17 @@ A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. + 類型 '{0}' 的 using 陳述式資源不能用於非同步方法或非同步 Lambda 運算式。 Using alias cannot be a 'ref' type. - Using alias cannot be a 'ref' type. + 使用別名不可以是 'ref' 類型。 'static' modifier must precede 'unsafe' modifier. - 'static' modifier must precede 'unsafe' modifier. + 'static' 修飾元必須在 'unsafe' 修飾元之前。 @@ -284,7 +284,7 @@ Only a 'using static' or 'using alias' can be 'unsafe'. - Only a 'using static' or 'using alias' can be 'unsafe'. + 只有 'using static' 或 'using alias' 可以是 'unsafe'。 @@ -729,7 +729,7 @@ Using a function pointer type in this context is not supported. - 不支援在屬性的 'typeof' 中使用函式指標類型。 + 不支援在此內容中使用函式指標類型。 @@ -929,7 +929,7 @@ Cannot use primary constructor parameter '{0}' in this context. - Cannot use primary constructor parameter '{0}' in this context. + 無法在此內容中使用主要建構函式參數 '{0}'。 @@ -1084,7 +1084,7 @@ Only a single partial type declaration may have a parameter list - 只有一筆記錄可以在部分宣告中包含參數清單 + 只有單一部分類型宣告可以有參數清單 @@ -1359,7 +1359,7 @@ A constructor declared in a 'struct' with parameter list must have a 'this' initializer that calls the primary constructor or an explicitly declared constructor. - 使用參數清單在 'record struct' 中宣告的建構函式,必須有呼叫主要建構函式或已明確宣告建構函式的 'this' 初始設定式。 + 在 'struct' 中宣告、具有參數清單的建構函式,必須有呼叫主要建構函式或已明確宣告建構函式的 'this' 初始設定式。 @@ -1394,12 +1394,12 @@ A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - A primary constructor parameter of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 唯讀類型的主要建構函式參數不能做為 ref 或 out 值 (類型的 init-only setter 或變數初始設定式中除外) Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) - Members of primary constructor parameter '{0}' of a readonly type cannot be used as a ref or out value (except in init-only setter of the type or a variable initializer) + 唯讀類型的主要建構函式參數 '{0}' 的成員不能做為 ref 或 out 值 (類型的 init-only setter 或變數初始設定式中除外) @@ -1414,17 +1414,17 @@ Cannot return primary constructor parameter '{0}' by reference. - Cannot return primary constructor parameter '{0}' by reference. + 無法依參考傳回主要建構函式參數 '{0}'。 A primary constructor parameter of a readonly type cannot be returned by writable reference - A primary constructor parameter of a readonly type cannot be returned by writable reference + 唯讀類型的主要建構函式參數無法由可寫入的參考傳回 Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference - Members of primary constructor parameter '{0}' of a readonly type cannot be returned by writable reference + 唯讀類型的主要建構函式參數 '{0}' 的成員無法由可寫入的參考傳回 @@ -1644,7 +1644,7 @@ Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout - Struct primary constructor parameter '{0}' of type '{1}' causes a cycle in the struct layout + 類型 '{1}' 的結構主要建構函式參數 '{0}' 在結構配置中導致循環 @@ -1729,7 +1729,7 @@ Unexpected parameter list. - Unexpected parameter list. + 未預期的參數清單。 @@ -1744,7 +1744,7 @@ '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. - '{0}' is defined in a module with an unrecognized RefSafetyRulesAttribute version, expecting '11'. + '{0}' 是在具有無法辨識的 RefSafetyRulesAttribute 版本的模組中定義,預期為 '11'。 @@ -1774,12 +1774,12 @@ Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member - Cannot use ref, out, or in primary constructor parameter '{0}' inside an instance member + 無法在執行個體成員內使用 ref、out 或 in 主要建立建構函式參數 '{0}' Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member - Cannot use primary constructor parameter '{0}' that has ref-like type inside an instance member + 無法使用執行個體成員內具有類似參考類型的主要建立函式參數 '{0}' @@ -1944,7 +1944,7 @@ primary constructors - primary constructors + 主要建構函式 @@ -1994,7 +1994,7 @@ using type alias - using type alias + 使用類型別名 @@ -2029,12 +2029,12 @@ The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 運算子不應該用於非同步方法中的參數或區域變數。 The '&' operator should not be used on parameters or local variables in async methods. - The '&' operator should not be used on parameters or local variables in async methods. + '&' 運算子不應該用於非同步方法中的參數或區域變數。 @@ -2139,12 +2139,12 @@ Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter '{0}' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + 參數 '{0}' 會擷取至包含類型的狀態,且其值也會傳遞給基礎建構函式。值也可能由基礎類別擷取。 Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. - Parameter is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well. + 參數會擷取至包含類型的狀態,且其值也會傳遞給基礎建構函式。值也可能由基礎類別擷取。 @@ -2549,7 +2549,7 @@ A constructor declared in a type with parameter list must have 'this' constructor initializer. - 在包含參數清單之記錄中宣告的構造函式,必須具有 'this' 建構函式初始設定式。 + 在類型中宣告、具有參數清單的建構函式,必須具有 'this' 建構函式初始設定式。 @@ -4433,12 +4433,12 @@ Parameter '{0}' is unread. - Parameter '{0}' is unread. + 參數 '{0}' 未讀取。 Parameter is unread. - Parameter is unread. + 參數未讀取。 @@ -10381,22 +10381,22 @@ You should consider suppressing the warning only if you're sure that you don't w The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] - The specified version string '{0}' does not conform to the required format - major[.minor[.build[.revision]]] + 指定的版本字串 '{0}' 不符合所需的格式 - major[.minor[.build[.revision]]] The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation - The specified version string '{0}' contains wildcards, which are not compatible with determinism. Either remove wildcards from the version string, or disable determinism for this compilation + 指定的版本字串 '{0}' 包含萬用字元,但這與確定性不相容。請移除版本字串中的萬用字元,或停用此編譯的確定性。 The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) - The specified version string '{0}' does not conform to the required format - major.minor.build.revision (without wildcards) + 指定的版本字串 '{0}' 不符合所需的格式: major.minor.build.revision (不含萬用字元) The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision - The specified version string '{0}' does not conform to the recommended format - major.minor.build.revision + 指定的版本字串 '{0}' 不符合建議的格式 - major.minor.build.revision diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs index 326ba54f0f9b2..1210b1997564c 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs @@ -3891,5 +3891,23 @@ .maxstack 3 } "); } + + [ConditionalFact(typeof(CoreClrOnly))] + public void SpanSlice() + { + string source = """ + using System; + class Program + { + static void M(Span s) + { + var x = s[1..^1]; + var y = s[^1]; + } + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); + comp.VerifyDiagnostics(); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs index 576acc53226fc..c7678cad8de0f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs @@ -15482,6 +15482,54 @@ public void AppendFormatted(T value) comp.VerifyDiagnostics(); } + [Fact] + public void RefEscape_ForEachExpression() + { + string source = """ + using System.Runtime.CompilerServices; + [InterpolatedStringHandler] + ref struct CustomHandler + { + public CustomHandler(int literalLength, int formattedCount, ref R r) : this() { r.Handler = this; } + public void AppendFormatted(int i) { } + } + ref struct R + { + public CustomHandler Handler; + } + ref struct Enumerable + { + public static Enumerable Create(ref R r, [InterpolatedStringHandlerArgument("r")] CustomHandler handler) => default; + public Enumerator GetEnumerator() => default; + } + ref struct Enumerator + { + public R Current => throw null; + public bool MoveNext() => false; + } + class Program + { + static void F(ref R r) + { + foreach (var i in Enumerable.Create(ref r, $"{1}")) + { + } + } + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); + comp.VerifyDiagnostics( + // (5,97): error CS8352: Cannot use variable 'out CustomHandler this' in this context because it may expose referenced variables outside of their declaration scope + // public CustomHandler(int literalLength, int formattedCount, ref R r) : this() { r.Handler = this; } + Diagnostic(ErrorCode.ERR_EscapeVariable, "this").WithArguments("out CustomHandler this").WithLocation(5, 97), + // (26,49): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference + // foreach (var i in Enumerable.Create(ref r, $"{1}")) + Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "r").WithLocation(26, 49), + // (26,52): error CS8347: Cannot use a result of 'CustomHandler.CustomHandler(int, int, ref R)' in this context because it may expose variables referenced by parameter 'r' outside of their declaration scope + // foreach (var i in Enumerable.Create(ref r, $"{1}")) + Diagnostic(ErrorCode.ERR_EscapeCall, @"$""{1}""").WithArguments("CustomHandler.CustomHandler(int, int, ref R)", "r").WithLocation(26, 52)); + } + [Theory, WorkItem(54703, "https://github.com/dotnet/roslyn/issues/54703")] [InlineData(@"$""{{ {i} }}""")] [InlineData(@"$""{{ "" + $""{i}"" + $"" }}""")] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs index 00a6cbb1eb21b..79dd439e040da 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs @@ -18818,10 +18818,10 @@ private void Handle(SyntaxNodeAnalysisContext context) MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[constructorDeclaration]; - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration).IsDefaultOrEmpty); - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.Initializer).IsDefaultOrEmpty); - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.Body).IsDefaultOrEmpty); - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.ExpressionBody).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration).IsEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.Initializer).IsEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.Body).IsEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(constructorDeclaration.ExpressionBody).IsEmpty); var x1Decl = GetOutVarDeclaration(tree, "x1"); var x1Ref = GetReferences(tree, "x1").ToArray(); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs index 7b8f313753f95..9167634ab8a04 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs @@ -7061,6 +7061,115 @@ static void TwoOutSpans(out Span a, out Span b) comp.VerifyDiagnostics(); } + [Fact] + public void Local_UsingStatementExpression() + { + string source = """ + using System; + struct S : IDisposable + { + public void Dispose() { } + } + ref struct R + { + public ref int F; + public R(ref int i) { F = ref i; } + public static implicit operator S(R r) => default; + } + class Program + { + static void Main() + { + int i = 0; + var x = new R(ref i); + using (x switch { R y => (S)y }) + { + } + } + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); + comp.VerifyDiagnostics(); + } + + [WorkItem(67493, "https://github.com/dotnet/roslyn/issues/67493")] + [Fact] + public void Local_SwitchStatementExpression() + { + string source = """ + ref struct R1 + { + public R2 F; + public R1(ref int i) { F = new R2(ref i); } + } + ref struct R2 + { + ref int _i; + public R2(ref int i) { _i = ref i; } + } + class Program + { + static R2 F() + { + int i = 0; + var x = new R1(ref i); + switch (x switch { { F: R2 y } => y }) + { + case R2 z: + return z; + } + } + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); + comp.VerifyDiagnostics( + // (20,24): error CS8352: Cannot use variable 'z' in this context because it may expose referenced variables outside of their declaration scope + // return z; + Diagnostic(ErrorCode.ERR_EscapeVariable, "z").WithArguments("z").WithLocation(20, 24)); + } + + [WorkItem(67493, "https://github.com/dotnet/roslyn/issues/67493")] + [Fact] + public void Local_ForEachExpression() + { + string source = """ + ref struct R + { + public ref int F; + public R(ref int i) { F = ref i; } + } + ref struct Enumerable + { + public ref int F; + public Enumerable(ref int i) { F = ref i; } + public Enumerator GetEnumerator() => new Enumerator(ref F); + } + ref struct Enumerator + { + public ref int F; + public Enumerator(ref int i) { F = ref i; } + public R Current => new R(ref F); + public bool MoveNext() => false; + } + class Program + { + static R F() + { + foreach (var y in 1 switch { int x => new Enumerable(ref x) }) + { + return y; + } + return default; + } + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); + comp.VerifyDiagnostics( + // (25,20): error CS8352: Cannot use variable 'y' in this context because it may expose referenced variables outside of their declaration scope + // return y; + Diagnostic(ErrorCode.ERR_EscapeVariable, "y").WithArguments("y").WithLocation(25, 20)); + } + [ConditionalFact(typeof(CoreClrOnly))] public void ParameterEscape() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs index 9f9b66b0594ce..0e0f8dd0617ae 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs @@ -6445,7 +6445,7 @@ private void Handle1(SyntaxNodeAnalysisContext context) MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[globalStatement.Parent]; - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(globalStatement.Statement).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(globalStatement.Statement).IsEmpty); Assert.Same(mm, syntaxTreeModel.GetMemberModel(globalStatement.Statement)); } @@ -6923,7 +6923,7 @@ private void Handle(CodeBlockAnalysisContext context) MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[unit]; - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsEmpty); Assert.Same(mm, syntaxTreeModel.GetMemberModel(unit)); } @@ -6991,7 +6991,7 @@ private void Handle(CodeBlockStartAnalysisContext context) MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[unit]; - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(unit).IsEmpty); Assert.Same(mm, syntaxTreeModel.GetMemberModel(unit)); } @@ -7077,7 +7077,7 @@ private void Handle1(SyntaxNodeAnalysisContext context) MemberSemanticModel mm = syntaxTreeModel.TestOnlyMemberModels[decl]; - Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(node).IsDefaultOrEmpty); + Assert.False(mm.TestOnlyTryGetBoundNodesFromMap(node).IsEmpty); Assert.Same(mm, syntaxTreeModel.GetMemberModel(node)); } diff --git a/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs b/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs index b1e4d9ef88c17..648e0de0ed442 100644 --- a/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { @@ -249,5 +250,26 @@ public static void FreeAll(this ArrayBuilder builder, Func + /// Realizes the OneOrMany and disposes the builder in one operation. + /// + public static OneOrMany ToOneOrManyAndFree(this ArrayBuilder builder) + { + if (builder.Count == 1) + { + var result = OneOrMany.Create(builder[0]); + builder.Free(); + return result; + } + else + { + return OneOrMany.Create(builder.ToImmutableAndFree()); + } + } + +#endif } } diff --git a/src/Compilers/Core/Portable/Collections/OrderPreservingMultiDictionary.cs b/src/Compilers/Core/Portable/Collections/OrderPreservingMultiDictionary.cs index 4b2c3c641eb37..c297078462611 100644 --- a/src/Compilers/Core/Portable/Collections/OrderPreservingMultiDictionary.cs +++ b/src/Compilers/Core/Portable/Collections/OrderPreservingMultiDictionary.cs @@ -9,6 +9,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Collections { @@ -153,6 +154,17 @@ IEnumerator IEnumerable.GetEnumerator() } } + public OneOrMany GetAsOneOrMany(K k) + { + if (_dictionary is object && _dictionary.TryGetValue(k, out var valueSet)) + { + Debug.Assert(valueSet.Count >= 1); + return valueSet.Count == 1 ? OneOrMany.Create(valueSet[0]) : OneOrMany.Create(valueSet.Items); + } + + return OneOrMany.Empty; + } + public bool Contains(K key, V value) { return _dictionary is object && diff --git a/src/Compilers/Core/Portable/Collections/StaticCast.cs b/src/Compilers/Core/Portable/Collections/StaticCast.cs index 9a869e8796138..790e4dbf078e4 100644 --- a/src/Compilers/Core/Portable/Collections/StaticCast.cs +++ b/src/Compilers/Core/Portable/Collections/StaticCast.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { @@ -12,5 +13,10 @@ internal static class StaticCast { return ImmutableArray.CastUp(from); } + + internal static OneOrMany From(OneOrMany from) where TDerived : class, T + { + return OneOrMany.CastUp(from); + } } } diff --git a/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs b/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs index d953a384bba96..c06ff30ef3dd7 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.PooledObjects; @@ -139,6 +140,22 @@ public OneOrMany Select(Func selector) OneOrMany.Create(_many.SelectAsArray(selector, arg)); } + public IEnumerable OfType() + { + return this.Count == 0 + ? Array.Empty() + : iterateElements(this); + + static IEnumerable iterateElements(OneOrMany @this) + { + foreach (var item in @this) + { + if (item is TResult result) + yield return result; + } + } + } + public T? FirstOrDefault(Func predicate) { if (HasOne) @@ -175,6 +192,27 @@ public OneOrMany Select(Func selector) return default; } + public static OneOrMany CastUp(OneOrMany from) where TDerived : class, T + { + return from.HasOne + ? new OneOrMany(from._one) + : new OneOrMany(ImmutableArray.CastUp(from._many)); + } + + public bool All(Func predicate) + { + foreach (var value in this) + { + if (!predicate(value)) + return false; + } + + return true; + } + + public bool Any() + => this.Count > 0; + public Enumerator GetEnumerator() => new(this); diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf index 1142859f81a3b..bd424d0cfd113 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + HintName {0} obsahuje neplatný segment {1} na pozici {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + HintName {0} není v aktuálním adresáři. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Neplatný typ instrumentace: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Byl očekáván symbol metody. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf index deed65e3726c2..14cda4ead43a0 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + Der hintName „{0}“ enthält ein ungültiges Segment „{1}“ an Position {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + Der hintName „{0}“ befindet sich nicht im aktuellen Verzeichnis. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Ungültiger Instrumentierungstyp: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Methodensymbol erwartet diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf index cc70b092a2898..a55f1661e3b33 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + HintName '{0}' contiene un segmento no válido '{1}' en la posición {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + El valor de hintName '{0}' no está dentro del directorio actual. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Clase de instrumentación no válida: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Se esperaba un símbolo de método diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf index 44c763b29be6e..b60481040d444 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + Le hintName '{0}' contient un segment non valide '{1}' à la position {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + Le '{0}' hintName ne se trouve pas dans le répertoire actif. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Genre d'instrumentation non valide : {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Symbole de méthode attendu diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf index 085e44275bd6f..69a969f5fb304 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + L'elemento hintName '{0}' contiene un segmento non valido '{1}' alla posizione {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + L'elemento '{0}' hintName non si trova nella directory corrente. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Il tipo di strumentazione non è valido: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + È previsto un simbolo di metodo diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf index 4ca14bd6675f8..3f5e57ae507b6 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + hintName '{0}' の位置 {2} に無効なセグメント '{1}' が含まれています。 {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + hintName '{0}' が現在のディレクトリ内にありません。 @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + 無効なインストルメンテーションの種類: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + メソッド シンボルが必要です diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf index fe58ab16711fe..83301453b7087 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + hintName '{0}'의 위치 {2}에 잘못된 세그먼트 '{1}'이(가) 있습니다. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + hintName '{0}'이(가) 현재 디렉터리에 없습니다. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + 잘못된 계측 종류: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + 메서드 기호가 필요합니다. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf index 33a3e97364cdd..2634caa310af2 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + Element hintName '{0}' zawiera nieprawidłowy segment '{1}' na pozycji {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + Nazwa wskazówki '{0}' nie znajduje się w bieżącym katalogu. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Nieprawidłowy rodzaj instrumentacji: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Oczekiwano symbolu metody diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf index 39e7769024440..9e2b508fcd86a 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + O hintName "{0}" contém um segmento inválido "{1}" na posição {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + O hintName "{0}" não está dentro do diretório atual. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Variante de instrumentação inválida: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Símbolo de método esperado diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf index 97c6ff55ebefd..eb430c56b7854 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + HintName "{0}" содержит недопустимый сегмент "{1}" в позиции {2}. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + HintName "{0}" находится вне текущего каталога. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Недопустимый тип инструментирования: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Ожидается символ метода diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf index 4d247ada4aea9..3a9340a865347 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + HintName '{0}', {2} konumunda geçersiz bir '{1}' segmenti içeriyor. {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + HintName '{0}' geçerli dizinde değil. @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + Geçersiz izleme türü: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + Yöntem sembolü bekleniyor diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf index 6c61d665197a1..3c7e70d1be55f 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + hintName“{0}”的段“{1}”(位于位置“{2}”)无效。 {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + hintName“{0}”不在当前目录中。 @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + 无效的检测类型: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + 应为方法符号 diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf index 16aa2ba61c20a..cf2d22a80c479 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf @@ -81,12 +81,12 @@ The hintName '{0}' contains an invalid segment '{1}' at position {2}. - The hintName '{0}' contains an invalid segment '{1}' at position {2}. + hintName '{0}' 的位置 {2} 包含無效的字元 '{1}'。 {0}: the provided hintname. {1}: the invalid segment, {2} the position it occurred at The hintName '{0}' is not within the current directory. - The hintName '{0}' is not within the current directory. + hintName '{0}' 不在目前的目錄內。 @@ -106,7 +106,7 @@ Invalid instrumentation kind: {0} - Invalid instrumentation kind: {0} + 檢測設備種類無效: {0} @@ -126,7 +126,7 @@ Method symbol expected - Method symbol expected + 預期的方法符號 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index 1162bde0283fb..2aad39e12293c 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -269,169 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Možnosti kompilátoru Visual Basic + Možnosti kompilátoru jazyka Visual Basic - VÝSTUPNÍ SOUBOR - --out:<soubor> Určuje název výstupního souboru. --target:exe Vytvoří konzolovou aplikaci (výchozí). +-out:<file> Určuje název výstupního souboru. +-target:exe Vytvoří aplikaci konzole (výchozí). (Krátký tvar: -t) --target:winexe Vytvoří aplikaci pro Windows. +-target:winexe Vytvoří aplikaci systému Windows. -target:library Vytvoří sestavení knihovny. --target:module Vytvoří modul, který lze přidat do +-target:module Vytvoří modul, který se dá přidat k sestavení. --target:appcontainerexe Vytvoří aplikaci pro Windows, která běží v kontejneru +-target:appcontainerexe Vytvoří aplikaci systému Windows, která běží v AppContainer. --target:winmdobj Vytvoří zprostředkující soubor metadat Windows. --doc[+|-] Vygeneruje soubor dokumentace XML. --doc:<soubor> Vygeneruje soubor dokumentace XML pro <soubor>. --refout:<soubor> Odkazuje na výstup sestavení k vygenerování. +-target:winmdobj Vytvoří pomocný soubor metadat systému Windows. +-doc[+|-] Generuje soubor dokumentace XML. +-doc:<file> Generuje soubor dokumentace XML do souboru <file>. +-refout:<file> Výstup referenčního sestavení, který se má vygenerovat. - VSTUPNÍ SOUBORY - --addmodule:<seznam_souborů> Odkazuje na metadata ze zadaných modulů. --link:<seznam_souborů> Vloží metadata ze zadaného definičního +-addmodule:<file_list> Odkazuje na metadata ze zadaných modulů. +-link:<file_list> Vloží metadata ze zadaného definičního sestavení. (Krátký tvar: -l) --recurse:<zástupný_symbol> Zahrne všechny soubory v aktuálním adresáři - a podadresářích podle specifikací - zástupných znaků. --reference:<seznam_souborů> Odkazuje ze zadaného +-recurse:<wildcard> Zahrne všechny soubory v aktuálním adresáři + a podadresářích podle + specifikace zástupných znaků. +-reference:<file_list> Odkazuje na metadata ze zadaného sestavení. (Krátký tvar: -r) --analyzer:<seznam_souborů> Spouští analyzátory z tohoto sestavení. +-analyzer:<file_list> Spustí analyzátory z tohoto sestavení. (Krátký tvar: -a) --additionalfile:<seznam_souborů> Další soubory, které nemají přímý vliv na generování - kódu, ale analyzátory je můžou použít pro - chyby a varování. +-additionalfile:<file list> Další soubory, které nemají přímý vliv na generování + kódu, ale můžou je používat analyzátory k vytváření + chyb nebo upozornění. - - ZDROJE - --linkresource:<údaj_o_zdroji> Propojí zadaný soubor jako zdroj - externího sestavení. - resinfo:<soubor>[,<název>[,public|private]] + - PROSTŘEDKY - +-linkresource:<resinfo> Propojuje zadaný soubor jako externí + prostředek sestavení. + resinfo:<file>[,<name>[,veřejný|soukromý]] (Krátký tvar: -linkres) --nowin32manifest Výchozí manifest by neměl být vložen - do oddílu manifestu výstupních dat PE. --resource:<údaj_o_zdroji> Přidá zadaný soubor jako zdroj - vloženého sestavení. - resinfo:<soubor>[,<název>[,public|private]] +-nowin32manifest Výchozí manifest by neměl být vložený + v oddílu manifestu výstupních dat PE. +-resource:<resinfo> Přidá zadaný soubor jako vložený + prostředek sestavení. + resinfo:<file>[,<name>[,veřejný|soukromý]] (Krátký tvar: -res) --win32icon:<soubor> Určuje soubor ikony Win32 (.ico) pro - výchozí zdroje Win32. --win32manifest:<soubor> Zadaný soubor se vloží do oddílu manifestu - výstupních dat PE. --win32resource:<soubor> Určuje soubor zdroje Win32 (.res). +-win32icon:<file> Určuje soubor ikony Win32 (.ico) pro + výchozí prostředky Win32. +-win32manifest:<file> Zadaný soubor je vložený do oddílu + manifestu výstupních dat PE. +-win32resource:<file> Určuje soubor prostředku Win32 (.res). - GENEROVÁNÍ KÓDU - -optimize[+|-] Povolí optimalizace. --removeintchecks[+|-] Odebere celočíselné kontroly. Ve výchozím nastavení je vypnuto. --debug[+|-] Vydá ladicí informace. --debug:full Vydá plné ladicí informace (výchozí). --debug:pdbonly Vydá jen ladicí informace pro PDB. --debug:portable Vydá ladicí informace pro všechny platformy. --debug:embedded Vydá ladicí informace pro všechny platformy do +-removeintchecks[+|-] Odebere kontroly dat typu integer. Výchozí hodnota je vypnutá. +-debug[+|-] Generuje ladicí informace. +-debug:full Generuje úplné ladicí informace (výchozí). +-debug:pdbonly Generuje úplné ladicí informace. +-debug:portable Generuje ladicí informace pro různé platformy. +-debug:embedded Generuje ladicí informace pro různé platformy do cílového souboru .dll nebo .exe. -deterministic Vytvoří deterministické sestavení - (včetně GUID verze modulu a časového razítka). + (včetně verze modulu GUID a časového razítka). -refonly Vytvoří referenční sestavení místo hlavního výstupu. --instrument:TestCoverage Vytvoří sestavení instrumentované pro shromažďování - informací o pokrytí. --sourcelink:<soubor> Určuje zdroj informací o propojení pro vložení do PDB. +-instrument:TestCoverage Vytvoří sestavení instrumentované ke shromažďování + informací o pokrytí. +-sourcelink:<file> Informace o odkazu na zdroj, který se má vložit do souboru PDB. - - CHYBY A VAROVÁNÍ - --nowarn Zakáže všechna varování. --nowarn:<číselný_seznam> Zakáže varování uvedená v seznamu. --warnaserror[+|-] Považuje všechna varování za chyby. --warnaserror[+|-]:<číselný_seznam> Považuje varování v seznamu za chyby. --ruleset:<soubor> Určuje soubor sady pravidel, který zakáže konkrétní + – CHYBY A UPOZORNĚNÍ - +-nowarn Zakáže všechna upozornění. +-nowarn:<number_list> Zakáže seznam jednotlivých upozornění. +-warnaserror[+|-] Považuje všechna upozornění za chyby. +-warnaserror[+|-]:<number_list> Považuje seznam upozornění za chyby. +-ruleset:<file> Určuje soubor sady pravidel, který zakáže konkrétní diagnostiku. --errorlog:<soubor>[,version=<verze_sarif>] - Určuje soubor pro protokolování veškeré diagnostiky kompilátorů - a analyzátorů ve formátu SARIF. - sarif_version:{1|2|2.1} Výchozí je 1. Hodnoty 2 i 2.1 - označují verzi SARIF 2.1.0. --reportanalyzer Ohlásí další informace analyzátoru, jako je - doba provádění. --skipanalyzers[+|-] Přeskočí provádění diagnostických analyzátorů. +-errorlog:<file>[,verze=<sarif_version>] + Určuje soubor k protokolování veškeré diagnostiky kompilátorů + a analyzátorů ve formátu SARIF. + sarif_version:{1|2|2.1} Výchozí hodnota je 1. 2 a 2.1 + obě znamenají SARIF verze 2.1.0. +-reportanalyzer Oznámí další informace o analyzátoru, například + čas spuštění. +-skipanalyzers[+|-] Přeskočí spuštění diagnostických analyzátorů. - JAZYK - --define:<seznam_symbolů> Deklaruje globální symboly podmíněné - kompilace. seznam_symbolů:název=hodnota,... +-define:<symbol_list> Deklaruje globální podmíněnou kompilaci + symbol(y). symbol_list:name=value,... (Krátký tvar: -d) --imports:<seznam_importů> Deklarujte globální importy pro obory názvů - v odkazovaných souborech metadat. - seznam_importů:obor_názvů,... --langversion:? Zobrazí povolené hodnoty pro jazykovou verzi. --langversion:<řetězec> Určuje jazykovou verzi, a to jako hodnotu - default (nejnovější hlavní verze) nebo - latest (nejnovější verze včetně podverzí) - nebo konkrétní verze, jako je 14 nebo 15.3. +-imports:<import_list> Deklaruje globální importy pro obory názvů + v odkazovaných souborech metadat. + import_list:namespace,... +-langversion:? Zobrazí povolené hodnoty pro verzi jazyka. +-langversion:<string> Určuje verzi jazyka, například + výchozí (nejnovější hlavní verze) nebo + nejnovější (nejnovější verze včetně podverzí), + nebo konkrétní verze jako 14 nebo 15.3. -optionexplicit[+|-] Vyžaduje explicitní deklaraci proměnných. -optioninfer[+|-] Povolí odvozování typů proměnných. --rootnamespace:<řetězec> Určuje kořenový obor názvů pro všechny deklarace +-rootnamespace:<string> Určuje kořenový obor názvů pro všechny deklarace typů. --optionstrict[+|-] Vynutí striktní sémantiku jazyka --optionstrict:custom Upozorní, pokud není - respektována striktní sémantika jazyka. --optioncompare:binary Určuje porovnání řetězců v binárním stylu. - Toto je výchozí nastavení. --optioncompare:text Určuje porovnání řetězců ve stylu textu. +-optionstrict[+|-] Vynutí striktní sémantiku jazyka. +-optionstrict:custom Zobrazí upozornění, pokud se nerespektuje striktní sémantika + jazyka. +-optioncompare:binary Určuje binární porovnávání řetězců. + Toto nastavení je výchozí. +-optioncompare:text Určuje textové porovnávání řetězců. - RŮZNÉ - --help Zobrazí tuto zprávu o použití. (Krátký tvar: -?) +-help Zobrazí tuto zprávu o využití. (Krátký tvar: -?) -noconfig Nezahrne automaticky soubor VBC.RSP. --nologo Nezobrazuje nápis o autorských právech kompilátoru --quiet Tichý režim výstupu +-nologo Nezobrazí hlavičku kompilátoru s uvedením autorských práv. +-quiet Bezobslužný režim výstupu. -verbose Zobrazí podrobné zprávy. --parallel[+|-] Souběžné sestavení --version Zobrazí číslo verze kompilátoru a ukončí se. +-parallel[+|-] Souběžné sestavení. +-version Zobrazí číslo verze kompilátoru a ukončí se. - - POKROČILÉ MOŽNOSTI - --baseaddress:<číslo> Základní adresa knihovny nebo modulu - (hex.). --checksumalgorithm:<alg> Zadá algoritmus pro výpočet kontrolního - součtu zdrojového souboru uloženého v PDB. Podporované hodnoty: + - ROZŠÍŘENÉ - +-baseaddress:<number> Základní adresa knihovny nebo modulu + (hex). +-checksumalgorithm:<alg> Určuje algoritmus pro výpočet kontrolního součtu + zdrojového souboru uloženého v souboru PDB. Podporované hodnoty: SHA1 nebo SHA256 (výchozí). --codepage:<číslo> Určuje znakovou stránku, která se má použít při otevírání +-codepage:<number> Určuje znakovou stránku, která se má použít při otevírání zdrojových souborů. --delaysign[+|-] Zpozdí podepsání sestavení jen pomocí veřejné - části klíče silného názvu. --publicsign[+|-] Veřejně podepíše sestavení jen pomocí veřejné +-delaysign[+|-] Zpožděné podepsání sestavení pouze pomocí veřejné části klíče silného názvu. --errorreport:<řetězec> Určuje, jak zpracovávat vnitřní chyby - kompilátoru. Musí mít hodnotu prompt, send, none nebo - queue (výchozí). --filealign:<číslo> Určuje zarovnání pro oddíly výstupního +-delaysign[+|-] Veřejné podepsání sestavení pouze pomocí veřejné + část klíče silného názvu. +-errorreport:<string> Určuje, jak zpracovávat interní chyby + kompilátoru; musí to být výzva, odeslání, žádné nebo fronta + (výchozí). +-generatedfilesout:<dir> Umístí soubory vygenerované během kompilace + do zadaného adresáře. +-filealign:<number> Určuje zarovnání použité pro oddíly výstupního souboru. --highentropyva[+|-] Povolí ASLR s vysokou entropií. --keycontainer:<řetězec> Určuje kontejner klíče se silným názvem. --keyfile:<soubor> Určuje soubor klíče se silným názvem. --libpath:<seznam_cestt> Seznam adresářů pro hledání odkazů na - metadata (Odděleno středníky.) --main:<třída> Určuje třídu nebo modul, který obsahuje - Sub Main. Může to být také třída, která +-highentropyva[+|-] Povolí technologii ASLR s vysokou entropií. +-keycontainer:<string> Určuje kontejner klíče se silným názvem. +-keyfile:<file> Určuje soubor klíče se silným názvem. +-libpath:<path_list> Seznam adresářů pro hledání odkazů + na metadata. (Položky oddělené středníkem.) +-main:<class> Určuje třídu nebo modul, který obsahuje + proceduru Sub Main. Může to být také třída, která dědí z System.Windows.Forms.Form. (Krátký tvar: -m) --moduleassemblyname:<řetězec> Název sestavení, jehož součástí bude tento - modul. --netcf Cílí na .NET Compact Framework. --nostdlib Neodkazujte na standardní knihovny - (soubor system.dll a VBC.RSP). +-moduleassemblyname:<string> Název sestavení, jehož součástí bude + tento modul. +-netcf Cílem je platforma .NET Compact Framework. +-nostdlib Neodkazuje na standardní knihovny + (system.dll a soubor VBC.RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... - Určuje mapování pro výstup s názvy zdrojových cest - z kompilátoru. --platform:<řetězec> Omezí platformy, na kterých může tento kód běžet; - musí mít hodnotu x86, x64, Itanium, arm, arm64 + Určuje mapování pro výstup názvů zdrojových cest podle + kompilátoru. +-platform:<string> Omezuje platformy, na kterých se může tento kód spouštět; + musí to být x86, x64, Itanium, arm, arm64 AnyCPU32BitPreferred nebo anycpu (výchozí). --preferreduilang Určuje upřednostňovaný název výstupního jazyka. +-preferreduilang Určuje preferovaný název výstupního jazyka. -nosdkpath Zakáže vyhledávání výchozí cesty sady SDK pro standardní sestavení knihovny. --sdkpath:<cesta> Umístění adresáře sady .NET Framework SDK +-sdkpath:<path> Umístění adresáře sady SDK .NET Framework (mscorlib.dll). --subsystemversion:<verze> Určuje verzi podsystému výstupních dat PE. - version:<číslo>[.<číslo>] --utf8output[+|-] Vydá výstup kompilátoru v kódování - znaků utf-8. -@<soubor> Vloží nastavení příkazového řádku z textového souboru. --vbruntime[+|-|*] Zkompiluje pomocí výchozího modulu runtime Visual Basic - nebo bez něho. --vbruntime:<soubor> Zkompiluje pomocí alternativního modulu runtime Visual Basic - v souboru <soubor>. +-subsystemversion:<version> Určuje verzi subsystému výstupních dat PE. + verze:<number>[.<number>] +-utf8output[+|-] Generuje výstup kompilátoru v kódování znaků + UTF-8. +@<file> Vloží nastavení příkazového řádku z textového souboru. +-vbruntime[+|-|*] Kompiluje s výchozím modulem runtime Visual Basic nebo + bez něj. +-vbruntime:<file> Kompiluje s alternativním modulem runtime Visual Basic + v souboru <file>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf index a271099dc906e..1c929d820e9ba 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.de.xlf @@ -269,169 +269,182 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Visual Basic-Compileroptionen + Visual Basic Compiler-Optionen - - AUSGABEDATEI - --out:<file> Gibt den Namen der Ausgabedatei an. --target:exe Erstellt eine Konsolenanwendung (Standard). + – AUSGABEDATEI – +-out:<file> Gibt den Namen der Ausgabedatei an. +-target:exe Erstellen Sie eine Konsolenanwendung (Standard). (Kurzform: -t) --target:winexe Erstellen einer Windows-Anwendung. --target:library Erstellt eine Bibliotheksassembly. --target:module Erstellen Sie ein Modul, das einer - Assembly hinzugefügt werden kann. --target:appcontainerexe Erstellen Sie eine Windows-Anwendung, die in - AppContainer ausgeführt wird. --target:winmdobj Erstellt eine Zwischendatei für Windows-Metadaten --doc[+|-] Generiert eine XML-Dokumentationsdatei. --doc:<file> Generiert eine XML-Dokumentationsdatei in <datei>. --refout:<file> Verweisassemblyausgabe zum Generieren von +-target:winexe Erstellen Sie eine Windows-Anwendung. +-target:library Erstellen Sie eine Bibliotheksbaugruppe. +-target:module Erstellen eines Moduls, das zu einem der folgenden Module hinzugefügt werden kann + Assembly. +-target:appcontainerexe Erstellen Sie eine Windows-Anwendung, die in + ausgeführt wird. + AppContainer. +-target:winmdobj Erstellen einer Windows-Metadaten-Zwischendatei +-doc[+|-] Erzeugt eine XML-Dokumentationsdatei. +-doc:<file> Erzeugt eine XML-Dokumentationsdatei nach <file>. +-refout:<file> Zu erzeugende Referenz-Assembly-Ausgabe - - INPUT FILES - --addmodule:<file_list> Verweismetadaten aus den angegebenen Modulen --link:<file_list> Einbetten von Metadaten aus der angegebenen Interop- - Assembly. (Kurzform: -l) --recurse:<wildcard> Schließen Sie alle Dateien im aktuellen Verzeichnis - und Unterverzeichnisse gemäß den - Platzhalterspezifikationen ein. --reference:<file_list> Verweismetadaten aus der angegebenen - Assembly. (Kurzform: -r) --analyzer:<file_list> Führt die Analysatoren von dieser Assembly aus - (Kurz form: -a) --additionalfile:<file list> Zusätzliche Dateien, die sich nicht direkt auf die Codegenerierung auswirken - aber von Analysatoren für verwendet werden können - Fehler oder Warnungen erzeugen. + - EINGABEDATEIEN - +-addmodule:<file_list> Verweis auf Metadaten aus den angegebenen Modulen +-link:<file_list> Metadaten aus der angegebenen Interop einbetten + Assembly. (Kurzform: -l) +-recurse:<wildcard> Alle Dateien im aktuellen Verzeichnis einbeziehen + und Unterverzeichnissen gemäß der + Platzhalterspezifikationen. +-reference:<file_list> Verweismetadaten aus dem angegebenen + Assembly. (Kurzform: -r) +-analyzer:<file_list> Die Analysatoren aus dieser Baugruppe ausführen + (Kurzform: -a) +-additionalfile:<file list> Zusätzliche Dateien, die nicht direkt Code + betreffen + Generation, kann aber von Analysegeräten zur Erzeugung von + verwendet werden + Fehler oder Warnungen. - - RESOURCES - + – RESSOURCEN – -linkresource:<resinfo> Verknüpft die angegebene Datei als externe Assemblyressource. - resinfo:<file>[,<name>[,public|private]] - (Kurz form: -linkres) --nowin32manifest Das Standardmanifest sollte nicht in den Manifestabschnitt des Ausgabe-PE eingebettet werden - Fügt die angegebene Datei als eingebettete Assemblyressource hinzu. --resource:<resinfo> Fügt die angegebene Datei als eingebettete Datei hinzu - Assembly Resource. - resinfo:<file>[,<name>[,public|private]] - (Short form: -res) --win32icon:<file> Gibt eine Win32-Symboldatei (.ico) für die - Standard-Win32-Ressourcen an.. --win32manifest:<file> Die bereitgestellte Datei wird in den Manifestabschnitt - des Ausgabe-PE eingebettet. --win32resource:<file> Gibt eine Win32-Ressourcendatei (.res) an. + resinfo:<Datei>[,<n[,public|private]] + (Kurzform: -linkres) +-nowin32manifest Das Standardmanifest sollte nicht eingebettet werden + im Manifestabschnitt der Ausgabe-PE. +-resource:<resinfo> Fügt die angegebene Datei als eingebettete + hinzu. + Assemblyressource. + resinfo:<Datei>[,<n[,public|private]] + (Kurzform: -res) +-win32icon:<filei> Legt eine Win32-Symboldatei (.ico) fest für die + Win32-Standardressourcen. +-win32manifest:<file> Die angegebene Datei ist in das Manifest + eingebettet + des PE-Ausgabeabschnitts. +-win32resource:<file> Gibt eine Win32-Ressourcendatei (RES) + an. - - CODE GENERATION - --optimize[+|-] Optimierungen aktivieren. --removeintchecks[+|-] Ganzzahlprüfungen entfernen. Standard aus. --debug[+|-] Debugging-Informationen ausgeben. --debug:full Vollständige Debugging-Informationen ausgeben (Standard). --debug:pdbonly Vollständige Debugging-Informationen ausgeben. + – CODEGENERIERUNG – +-optimize[+|-] Aktiviert Optimierungen. +-removeintchecks[+|-] Ganzzahlüberprüfungen entfernen. Standard aus. +-debug[+|-] Debuginformationen ausgeben. +-debug:full Gibt vollständige Debuginformationen aus (Standard). +-debug:pdbonly Gibt vollständige Debuginformationen aus. -debug:portable Gibt plattformübergreifende Debugging-Informationen aus. --debug:embedded Gibt plattformübergreifende Debugging-Informationen - in die Ziel .dll or .exe. --deterministische « - (mit Moduleversion GUID und timestamp) --refonly Erstellen Sie anstelle der Hauptausgabe eine Referenzbaugruppe --instrument:TestCoverage Produzieren Sie eine zum Sammeln instrumentierte Baugruppe - coverage information +-debug:embedded: Gibt plattformübergreifende Debuginformationen an + die ZIEL-DLL oder EXE-Datei. +–deterministisches Erstellen einer deterministischen Assembly + (einschließlich Modulversions-GUID und Zeitstempel) +-refonly Erzeugt eine Referenz-Assembly anstelle der Hauptausgabe +-instrument:TestCoverage Erstellen Sie eine Baugruppe, für die Erfassung von + Abdeckungsinformationen -sourcelink:<file> Quelllinkinformationen zum Einbetten in PDB. - - ERRORS uND WARNINGS - --nowarn Disable all warnings. --nowarn:<number_list> Deaktivieren Sie eine Liste mit einzelnen Warnungen. --warnaserror[+|-] Behandeln Sie alle Warnungen als Fehler. --warnaserror[+|-]:<number_list> Behandeln Sie eine Liste mit Warnungen als Fehler. --ruleset:<file> Geben Sie eine Regelsatzdatei an, die bestimmte deaktiviert - diagnostics. + – FEHLER UND WARNUNGEN – +-nowarn Deaktiviert alle Warnungen. +-nowarn:<number_list> Deaktiviert eine Liste einzelner Warnungen. +-warnaserror[+|-] Alle Warnungen als Fehler behandeln. +-warnaserror[+|-]:<number_list> Eine Liste von Warnungen als Fehler behandeln. +-ruleset:<datei> Geben Sie eine Regelsatzdatei an, die bestimmte + deaktiviert + Diagnose. -errorlog:<file>[,version=<sarif_version>] - Geben Sie eine Datei an, um alle Compiler und Analysatoren zu protokollieren - diagnostics in SARIF format. - sarif_version:{1|2|2.1} Default is 1. 2 and 2.1 - both mean SARIF version 2.1.0. --reportanalyzer Melden Sie zusätzliche Analysatorinformationen, wie z + Geben Sie eine Datei zum Protokollieren aller Compiler- und Analysetools + an + Diagnose im SARIF-Format. + sarif_version:{1|2|2.1} Der Standardwert ist 1. 2- und 2.1- + beide bedeuten SARIF Version 2.1.0. +-reportanalyzer Weitere Analyseinformationen melden, z. B. Ausführungszeit. --skipanalyzers[+|-] Ausführung von Diagnoseanalysatoren überspringen. +-skipanalyzers[+|-] Ausführung von Diagnoseanalysetools überspringen. - - LANGUAGE - --define:<symbol_list> Deklarieren Sie die globale bedingte Kompilierung + – SPRACHE – +-define:<symbol_list> Deklarieren der globalen bedingten Kompilierung symbol(s). symbol_list:name=value,... (Kurzform: -d) --imports:<import_list> Deklariert globale Imports für Namespaces in - referenzierten Metadatendateien. +-imports:<import_list> Deklarieren globaler Importe für Namespaces in + Metadatendateien, auf die verwiesen wird. import_list:namespace,... --langversion:? Zeigen Sie die zulässigen Werte für die Sprachversion an --langversion:<string> Specify language version such as - `default` (latest major version), or - `latest` (latest version, including minor versions), - or specific versions like `14` or `15.3` --optionexplicit[+|-] Require explicit declaration of variables. --optioninfer[+|-] Allow type inference of variables. --rootnamespace:<string> Specifies the root Namespace for all type - declarations. --optionstrict[+|-] Enforce strict language semantics. --optionstrict:custom Warn when strict language semantics are not - respected. --optioncompare:binary Specifies binary-style string comparisons. +-langversion:? Anzeigen der zulässigen Werte für die Sprachversion +-langversion:<string> Sprachversion angeben, z. B. + "default" (neueste Hauptversion) oder + "latest" (neueste Version, einschließlich Nebenversionen), + oder bestimmte Versionen wie "14" oder "15.3" +-optionexplicit[+|-] Erfordert eine explizite Deklaration von Variablen. +-optioninfer[+|-] Typrückschluss von Variablen zulassen. +-rootnamespace:<string> Gibt den Stammnamespace an für alle Typen + Deklarationen. +-optionstrict[+|-] Erzwingen Sie strenge Sprachsemantik. +-optionstrict: custom Warnen, wenn keine strikte Sprachsemantik + Respektiert. +-optioncompare:binary Gibt Zeichenfolgenvergleiche im Binärformat an. Dies ist die Standardeinstellung. --optioncompare:text Gibt Zeichenfolgenvergleiche im Textstil an. +-optioncompare:text Gibt Zeichenfolgenvergleiche im Textformat an. - - MISCELLANEOUS - --help Zeigt diese Nutzungsmeldung an. (Short form: -?) --noconfig Do not auto-include VBC.RSP file. --nologo Do not display compiler copyright banner. --quiet Quiet output mode. --verbose Display verbose messages. --parallel[+|-] Concurrent build. --version Display the compiler version number and exit. + – SONSTIGES – +-help Zeigt diese Nutzungsmeldung an. (Kurzform: -?) +-noconfig VBC nicht automatisch einschließen. RSP-Datei. +-nologo Das Copyrightbanner des Compilers wird nicht angezeigt. +-quiet Stiller Ausgabemodus. +-verbose Zeigt ausführliche Meldungen an. +-parallel[+|-] Gleichzeitiger Build. +-version Zeigt die Compilerversionsnummer an und beendet sie. - - ADVANCED - --baseaddress:<number> The base address for a library or module + – ERWEITERT – +-baseaddress:<number> Die Basisadresse für eine Bibliothek oder ein Modul (hex). --checksumalgorithm:<alg> Specify algorithm for calculating source file - checksum stored in PDB. Unterstützte Werte sind: - SHA1 or SHA256 (default). --codepage:<number> Specifies the codepage to use when opening - source files. --delaysign[+|-] Delay-sign the assembly using only the public - portion of the strong name key. --publicsign[+|-] Public-sign the assembly using only the public - portion of the strong name key. --errorreport:<string> Specifies how to handle internal compiler - errors; must be prompt, send, none, or queue - (default). --filealign:<number> Specify the alignment used for output file - sections. --highentropyva[+|-] Enable high-entropy ASLR. --keycontainer:<string> Specifies a strong name key container. --keyfile:<file> Specifies a strong name key file. --libpath:<path_list> List of directories to search for metadata - references. Semikolon getrennt.) --main:<class> Gibt die Klasse oder das Modul an, das Sub Main enthält. - Sub Main. Es kann auch eine Klasse sein, die - von System.Windows.Forms.Form erbt. - (Short form: -m) --moduleassemblyname:<string> Name der Assembly, in der dieses Modul enthalten sein wird - be a part of. --netcf Target the .NET Compact Framework. --nostdlib Do not reference standard libraries - (system.dll and VBC.RSP file). +-checksumalgorithm:<alg> Angeben eines Algorithmus zum Berechnen der Quelldatei + Prüfsumme, die in PDB gespeichert ist. Folgende Werte werden unterstützt: + SHA1 oder SHA256 (Standard). +-codepage:<number> Gibt die Codepage an, die beim Öffnen von +verwendet werden soll. + Quelldateien. +-delaysign[+|-] Verzögert das Signieren der Assembly mit nur dem öffentlichen + Teil des Schlüssels mit starkem Namen. +-publicsign[+|-] Signiert die Assembly nur mit dem öffentlichen + Teil des Schlüssels mit starkem Namen. +-errorreport:<string> Gibt an, wie interne Compiler- +behandelt werden. + Fehler; muss "prompt", "send", "none" oder "queue" sein + (Standard). +-generatedfilesout:<dir> Platzieren Sie Dateien, die während der Kompilierung generiert wurden, im + angegebenes Verzeichnis. +-filealign:<number> Geben Sie die Ausrichtung an, die für die Ausgabedatei verwendet wird, + Bereichen. +-highentropyva[+|-] Aktivieren Sie ASLR mit hoher Entropie. +-keycontainer:<string> Gibt einen Schlüsselcontainer mit starkem Namen an. +-keyfile:<file> Gibt eine Schlüsseldatei mit starkem Namen an. +-libpath:<path_list> Liste der Verzeichnisse für die Suche nach Metadaten + Verweise. (Durch Semikolon getrennt.) +-main:<class> Gibt die Klasse oder das Modul an, die bzw. das + Unterhaupt. Es kann sich auch um eine Klasse + erbt von System.Windows.Forms.Form. + (Kurzform: -m) +-moduleassemblyname:<string> Name der Assembly, die dieses Modul + ein Teil von sein. +-netcf Ziel der .NET Compact Framework. +-nostdlib Nicht auf Standardbibliotheken verweisen + (system.dll und VBC. RSP-Datei). -pathmap:<K1>=<V1>,<K2>=<V2>,... - Specify a mapping for source path names output by - the compiler. --platform:<string> Limit which platforms this code can run on; - must be x86, x64, Itanium, arm, arm64 - AnyCPU32BitPreferred or anycpu (default). --preferreduilang Specify the preferred output language name. --nosdkpath Disable searching the default SDK path for standard library assemblies. --sdkpath:<path> Location of the .NET Framework SDK directory + Geben Sie eine Zuordnung für Quellpfadnamen an, die von +ausgegeben werden. + der Compiler. +-platform:<string> Schränken Sie ein, auf welchen Plattformen dieser Code ausgeführt werden kann; + muss x86, x64, Itanium, arm, arm64 + AnyCPU32BitPreferred oder anycpu (Standard). +-preferreduilang Geben Sie den Namen der bevorzugten Ausgabesprache an. +-nosdkpath Deaktiviert das Durchsuchen des STANDARD-SDK-Pfads nach Standardbibliotheksassemblys. +-sdkpath:<path> Speicherort des .NET Framework SDK-Verzeichnisses (mscorlib.dll). --subsystemversion:<version> Specify subsystem version of the output PE. +-subsystemversion:<version> Geben Sie die Subsystemversion des Ausgabe-PE an. version:<number>[.<number>] --utf8output[+|-] Emit compiler output in UTF-8 character - encoding. -@<file> Insert command-line settings from a text file --vbruntime[+|-|*] Compile with/without the default Visual Basic - runtime. --vbruntime:<file> Compile with the alternate Visual Basic - runtime in <file>. +-utf8output[+|-] Compilerausgabe in UTF-8-Zeichen ausgeben + Codierung. +@<file> Befehlszeileneinstellungen aus einer Textdatei einfügen +-vbruntime[+|-|*] Kompilieren mit/ohne standardbasierte Visual Basic + Laufzeit. +-vbruntime:<datei> Kompilieren mit dem alternativen Visual Basic + Runtime in <datei>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf index 2f0265573fd53..c7f1499382bcf 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.es.xlf @@ -269,169 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Opciones del compilador de Visual Basic + Opciones del compilador de Visual Basic - ARCHIVO DE SALIDA - --out:<archivo> Especifica el nombre del archivo de salida. +-out:<file> Especifica el nombre del archivo de salida. -target:exe Crear una aplicación de consola (predeterminado). (Forma corta: -t) -target:winexe Crear una aplicación Windows. -target:library Crear un ensamblado de biblioteca. --target:module Crear un módulo que se pueda agregar a un +-target:module Crear un módulo que se puede agregar a un ensamblado. -target:appcontainerexe Crear una aplicación Windows que se ejecute en AppContainer. -target:winmdobj Crear un archivo intermedio de metadatos de Windows --doc[+|-] Genera un archivo de documentación XML. --doc:<archivo> Genera un archivo de documentación XML para <archivo>. --refout:<archivo> Salida de ensamblado de referencia +-doc[+|-] Genera el archivo de documentación XML. +-doc:<file> Genera el archivo de documentación XML para <file>. +-refout:<file> Salida del ensamblado de referencia para generar - ARCHIVOS DE ENTRADA - --addmodule:<lista de archivos> Hacer referencia a los metadatos desde los módulos especificados --link:<lista de archivos> Insertar metadatos del - ensamblado de interoperabilidad especificado. (Forma corta: -l) --recurse:<carácter comodín> Incluir todos los archivos en el directorio actual - y subdirectorios según las - especificaciones del carácter comodín. --reference:<lista de archivos> Hacer referencia a los metadatos desde el - ensamblado especificado. (Forma corta: -r) --analyzer:<lista de archivos> Ejecutar los analizadores desde este ensamblado +-addmodule:<file_list> Hace referencia a los metadatos de los módulos especificados +-link:<file_list> Incrustar metadatos de la interoperabilidad especificada + ensamblado. (Forma corta: -l) +-recurse:<wildcard> Incluir todos los archivos del directorio actual + y subdirectorios según el + especificaciones de caracteres comodín. +-reference:<file_list> Metadatos de referencia del archivo o los archivos de ensamblado especificados + ensamblado. (Forma corta: -r) +-analyzer:<file_list> Ejecute los analizadores desde este ensamblado (Forma corta: -a) --additionalfile:<lista de archivos> Archivos adicionales que no afectan directamente la - generación de código, pero que pueden ser utilizados por los analizadores para generar +-additionalfile:<file list> Archivos adicionales que no afectan directamente al código + generación, pero los analizadores pueden usarse para producir errores o advertencias. - RECURSOS - --linkresource:<resinfo> Vincula el archivo especificado como - recurso de ensamblado externo. - resinfo:<archivo>[,<nombre>[,public|private]] +-linkresource:<resinfo> Vincula el archivo especificado como uno externo + recurso de ensamblado. + resinfo:<file>[,<name>[,public|private]] (Forma corta: -linkres) --nowin32manifest No se debe insertar el manifiesto predeterminado +-nowin32manifest El manifiesto predeterminado no debe incrustarse en la sección de manifiesto del PE de salida. --resource:<resinfo> Agrega el archivo especificado como - recurso de ensamblado insertado. - resinfo:<archivo>[,<nombre>[,public|private]] +-resource:<resinfo> Agrega el archivo especificado como insertado + recurso de ensamblado. + resinfo:<file>[,<name>[,public|private]] (Forma corta: -res) --win32icon:<archivo> Especifica un archivo de icono de Win32 (.ico) para los - recurso predeterminados de Win32. --win32manifest:<archivo> El archivo proporcionado está insertado en la sección del - manifiesto del PE de salida. --win32resource:<archivo> Especifica un archivo de recurso de Win32 (.res). +-win32icon:<file> Especifica un archivo de icono de Win32 (.ico) para el + Recursos de Win32 predeterminados. +-win32manifest:<file> El archivo proporcionado se incrusta en el manifiesto + sección del PE de salida. +-win32resource:<file> Especifica el archivo de recursos Win32 (.res). - GENERACIÓN DE CÓDIGO - -optimize[+|-] Habilitar optimizaciones. -removeintchecks[+|-] Quitar comprobaciones de enteros. Desactivado de forma predeterminada. -debug[+|-] Emitir información de depuración. --debug:full Emitir información de depuración completa (predeterminado). +-debug:full Emitir información de depuración completa (de forma predeterminada). -debug:pdbonly Emitir información de depuración completa. --debug:portable Emitir información de depuración multiplataforma. --debug:embedded Emitir información de depuración multiplataforma en - el .dll o .exe. de destino --deterministic Producir un ensamblado determinista - (con el GUID y la marca de tiempo de la versión del módulo) --refonly Producir un ensamblado de referencia en lugar de la salida principal --instrument:TestCoverage Producir un ensamblado instrumentado para recopilar +-debug:portable Emite información de depuración multiplataforma. +-debug:embedded Emite información de depuración multiplataforma en + el archivo .dll o .exe de destino. +-deterministic Produce un ensamblado determinista + (incluyendo el GUID de la versión del módulo y la marca de tiempo) +-refonly Genera un ensamblado de referencia en lugar de la salida principal +-instrument:TestCoverage Produce un ensamblado instrumentado para recopilar información de cobertura --sourcelink:<archivo> Información del vínculo de origen para insertar en el PDB. +-sourcelink:<file> Información del vínculo de origen para insertar en el archivo PDB. - ERRORES Y ADVERTENCIAS - --nowarn Desactivar todas las advertencias. --nowarn:<lista_números> Desactivar una lista de advertencias individuales. +-nowarn Deshabilitar todas las advertencias. +-nowarn:<number_list> Deshabilitar una lista de advertencias individuales. -warnaserror[+|-] Tratar todas las advertencias como errores. --warnaserror[+|-]:<lista_números> Tratar una lista de advertencias como errores. --ruleset:<archivo> Especificar un archivo de conjunto de reglas que desactive - diagnósticos específicos. --errorlog:<archivo>[,versión=<versión_sarif>] - Especificar un archivo para registrar todos los - diagnósticos de compilador y de analizador en formato SARIF. - versión_sarif:{1|2|2.1} El valor predeterminado es 1. 2 y 2.1 - ambos se refieren a la versión de SARIF 2.1.0. --reportanalyzer Informar de información adicional de analizador, como el - tiempo de ejecución. --skipanalyzers[+|-] Omitir la ejecución de los analizadores de diagnóstico. +-warnaserror[+|-]:<number_list> Trate una lista de advertencias como errores. +-ruleset:<file> Especifique un archivo de conjunto de reglas que deshabilite específicos + diagnósticos. +-errorlog:<file>[,version=<sarif_version>] + Especifique un archivo para registrar todo lo del compilador y el analizador + diagnósticos en formato SARIF. + sarif_version:{1|2|2.1} El valor predeterminado es 1. 2 and 2.1 + ambos referencian a la versión 2.1.0 media de SARIF. +-reportanalyzer Informar información adicional del analizador, como + hora de ejecución. +-skipanalyzers[+|-] Omitir la ejecución de analizadores de diagnóstico. - - LENGUAJE - --define:<lista_de_símbolos> Declarar símbolos globales de compilación condicional - . symbol_list:name=value,... + - IDIOMA - +-define:<symbol_list> Declarar compilación condicional global + símbolos. symbol_list:name=value,... (Forma corta: -d) --imports:<importar_lista> Declarar importaciones globales para espacios de nombres en - archivos de metadatos a los que se hace referencia. +-imports:<import_list> Declarar importaciones globales para espacios de nombres en + archivos de metadatos de referencia. import_list:namespace,... --langversion:? Mostrar los valores permitidos para la versión de lenguaje --langversion:<cadena> Especificar la versión de lenguaje como - “predeterminada” (última versión principal) o - “última” (última versión, incluidas versiones secundarias), - o versiones específicas como “14” o “15.3” --optionexplicit[+|-] Requerir una declaración explícita de variables. --optioninfer[+|-] Permitir la inferencia de tipos de las variables. --rootnamespace:<cadena> Especifica el espacio de nombres raíz para todas las - declaraciones de tipos. +-langversion:? Muestra los valores permitidos para la versión del lenguaje +-langversion:<string> Especifique la versión de idioma como + "predeterminado" (versión principal más reciente) o + "más reciente" (versión más reciente, incluidas las versiones secundarias), + o versiones específicas, como "14" o "15.3" +-optionexplicit[+|-] Requerir la declaración explícita de variables. +-optioninfer[+|-] Permitir inferencia de tipos de variables. +-rootnamespace:<string> Especificar el espacio de nombres de la raíz de todos los tipos + declaraciones. -optionstrict[+|-] Aplicar una semántica de lenguaje estricta. --optionstrict:custom Advertir cuando la semántica de lenguaje estricta no - se respete. +-optionstrict:custom Advertir cuando la semántica estricta del lenguaje no sea + respetada. -optioncompare:binary Especifica comparaciones de cadenas de estilo binario. Este es el valor predeterminado. --optioncompare:text Especifica comparaciones de cadenas de estilo de texto. +-optioncompare:text Especifica comparaciones de cadenas de estilo binario. - VARIOS - --help Mostrar este mensaje de utilización. (Forma corta: -?) --noconfig No incluir automáticamente archivo VBC.RSP. --nologo No mostrar banner de propiedad intelectual del compilador. +-help Mostrar este mensaje de uso. (Forma corta: -?) +-noconfig No incluir automáticamente el archivo VBC.RSP. +-nologo No mostrar la pancarta de copyright del compilador. -quiet Modo de salida silencioso. -verbose Mostrar mensajes detallados. -parallel[+|-] Compilación simultánea. --version Mostrar la salida y el número de versión del compilador. +-version Mostrar el número de versión del compilador y salir. - AVANZADO - --baseaddress:<número> La dirección base de una librería o módulo +-baseaddress:<number> Dirección base de la biblioteca o módulo (hex). --checksumalgorithm:<alg> Especificar el algoritmo para calcular el archivo de origen - suma de comprobación almacenada en el PDB. Valores admitidos: - SHA1 o SHA256 (predeterminado). --codepage:<número> Especificar la página de códigos que hay que usar para abrir - los archivos de origen. --delaysign[+|-] Retrasar la firma del ensamblado usando solo la parte - pública de la clave del nombre seguro. --publicsign[+|-] Firmar el ensamblado usando solo la parte - pública de la clave de nombre seguro. --errorreport:<cadena> Especificar cómo tratar los errores del compilador - interno; debe ser prompt, send, none o queue +-checksumalgorithm:<alg> Especifique el algoritmo para calcular el archivo de origen + suma de comprobación almacenada en PDB. Los valores admitidos son: + SHA1 o SHA256 (valor predeterminado). +-codepage:<number> Especifica la página de códigos que se vaya a utilizar al abrir + archivos de código fuente. +-delaysign[+|-] Retrasar la firma del ensamblado usando solo el público + parte de la clave de nombre seguro. +-publicsign[+|-] Firmar públicamente el ensamblado usando solo el público + parte de la clave de nombre seguro. +-errorreport:<string> Especifica cómo controlar el compilador interno + errores; debe ser solicitar, enviar, ninguno o en cola (predeterminado). --filealign:<número> Especificar la alineación utilizada para las secciones - del archivo de salida. +-generatedfilesout:<dir> Colocar archivos generados durante la compilación en el + directorio especificado. +-filealign:<number> Especificar la alineación utilizada por los archivos de salida + secciones. -highentropyva[+|-] Habilitar ASLR de alta entropía. --keycontainer:<cadena> Especifica un contenedor de la clave del nombre seguro. --keyfile:<archivo> Especifica un archivo de la clave de nombre seguro. --libpath:<lista_rutas_acceso> Lista de directorios para buscar referencias de - metadatos. (Delimitado por punto y coma.) --main:<clase> Especifica la clase o el módulo que contiene - Sub Main. También puede ser una clase que - se hereda de System.Windows.Forms.Form. +-keycontainer:<string> Especifica un contenedor de claves de nombre seguro. +-keyfile:<file> Especifica un archivo de clave de nombre seguro. +-libpath:<path_list> Lista de directorios para buscar metadatos + referencias. (Delimitado por punto y coma). +-main:<clase> Especifica la clase o el módulo que contenga + Subelemento principal. También puede ser una clase que + hereda de System.Windows.Forms.Form. (Forma corta: -m) --moduleassemblyname:<cadena> Nombre del ensamblado del que este módulo - formará parte. --netcf Definir como objetivo .NET Compact Framework. --nostdlib No hacer referencia a las bibliotecas estándar +-moduleassemblyname:<string> Nombre del ensamblado del que este módulo + formar parte de. +-netcf Destino de .NET Compact Framework. +-nostdlib No hacer referencia a bibliotecas estándar (archivo system.dll y VBC.RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... - Especificar una asignación para los nombres de ruta de origen resultantes - del compilador. --platform:<cadena> Limitar en qué plataformas puede ejecutarse este código; + Especifique una asignación para los nombres de ruta de acceso de origen generados por + el compilador. +-platform:<string> Limitar en qué plataformas se puede ejecutar este código; debe ser x86, x64, Itanium, arm, arm64 - AnyCPU32BitPreferred o anycpu (predeterminado). --preferreduilang Especificar el nombre de lenguaje de salida preferido. --nosdkpath Desactivar la búsqueda de la ruta de acceso predeterminada del SDK para ensamblados de biblioteca estándar. --sdkpath:<ruta de acceso> Ubicación del directorio del SDK de .NET Framework + AnyCPU32BitPreferred o anycpu (valor predeterminado). +-preferreduilang Especifique el nombre del idioma de salida preferido. +-nosdkpath Deshabilita la búsqueda de rutas de acceso SDK predeterminadas para la biblioteca estándar. +-sdkpath:<path> Ubicación del directorio de .NET Framework SDK (mscorlib.dll). --subsystemversion:<versión> Especificar la versión de subsistema del PE de salida. - versión:<número>[.<número>] --utf8output[+|-] Emitir salida del compilador en codificación de caracteres - UTF-8. -@<archivo> Insertar configuración de línea de comandos desde un archivo de texto --vbruntime[+|-|*] Compilar con/sin el runtime predeterminado de - Visual Basic. --vbruntime:<archivo> Compilar con el runtime alternativo de - Visual Basic en <archivo>. +-subsystemversion:<version> Especificar versión del subsistema del PE de salida. + version:<number>[.<number>] +-utf8output[+|-] Emitir salida del compilador en caracteres UTF-8 + codificación. +@<file> Insertar la configuración de línea de comando de un archivo de texto +-vbruntime[+|-|*] Compilar con o sin el Visual Basic predeterminado + ejecución. +-vbruntime:<file> Compilar con el Visual Basic alternativo + tiempo de ejecución en <file>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index 9e003ef529bfa..8a6e2e25c0f1c 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -269,169 +269,183 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Options du compilateur Visual Basic + Options du compilateur Visual Basic - – FICHIER DE SORTIE - + - FICHIER DE SORTIE - -out:<file> Spécifie le nom du fichier de sortie. --target:exe Créez une application console (par défaut). +-target:exe Créer une application console (par défaut). (Forme abrégée : -t) --target:winexe Créez une application Windows. --target:library Créez un assembly de bibliothèque. --target:module Créez un module qui peut être ajouté à un - assembly. --target:appcontainerexe Créez une application Windows qui s’exécute dans +-target:winexe Créer une application Windows. +-target:library Créer un assembly de bibliothèque. +-target:module Créer un module qui peut être ajouté à un + assembly. +-target:appcontainerexe Créer une application Windows qui s’exécute dans AppContainer. --target:winmdobj Créez un fichier intermédiaire de métadonnées Windows --doc[+|-] Génère un fichier de documentation XML. --doc:<file> Génère le fichier de documentation XML pour <fichier>. --refout:<file> Sortie d’assembly de référence pour générer des +-target:winmdobj Créer un fichier intermédiaire de métadonnées Windows +-doc[+|-] Génère un fichier de documentation XML. +-doc:<file> Génère le fichier de documentation XML pour <fichier>. +-refout:<file> Sortie d’assembly de référence pour générer - – FICHIERS D'ENTRÉE - --addmodule:<file_list> Métadonnées de référence à partir des modules spécifiés --link:<file_list> Incorporez des métadonnées à partir de l’assembly d’interopérabilité - spécifié. (Forme abrégée : -l) --recurse:<wildcard> Inclure tous les fichiers dans le répertoire actuel - et les sous-répertoires en fonction des spécifications de caractères génériques - . --reference:<file_list> métadonnées de référence de l’assembly - spécifié. (Forme abrégée : -r) --analyzer:<file_list> Exécute les analyseurs de cette assembly - (Forme abrégée : -a) --additionalfile:<file_list> Fichiers supplémentaires qui n'affectent pas directement la - génération de code mais qui peuvent être utilisés par les analyseurs pour produire des - erreurs ou des avertissements. + - FICHIERS D’ENTRÉE - +-addmodule:<file_list> Métadonnées de référence des modules spécifiés +-link:<file_list> Incorporer des métadonnées à partir du +d’interopérabilité spécifié + assembly. (Forme abrégée : -l) +-recurse:<wildcard> Inclure tous les fichiers dans le répertoire actuel + et sous-répertoires en fonction des + spécifications de caractères génériques. +-reference:<file_list> Métadonnées de référence à partir du +spécifié + assembly. (Forme abrégée : -r) +-analyzer:<file_list> Exécuter les analyseurs à partir de cet assembly + (Forme abrégée : -a) +-additionalfile:<file> Fichiers supplémentaires qui n’affectent pas directement le code + mais peut être utilisé par les analyseurs pour produire des + erreurs ou avertissements. - - RESSOURCES - - -linkresource:<resinfo> Lie le fichier spécifié en tant que ressource d' - assembly externe. - resinfo:<fichier>[,<nom>[,public|privé]] + - RESSOURCES - +-linkresource:<resinfo> Lie le fichier spécifié en tant que +externe + ressource d’assembly. + resinfo:<file>[,<name>[,public|private]] (Forme abrégée : -linkres) - -nowin32manifest Le manifeste par défaut ne doit pas être intégré dans la section - manifeste du PE de sortie. --resource:<resinfo> Ajoute le fichier spécifié comme - ressource d'assembly incorporée. - resinfo:<fichier>[,<nom>[,public|privé]] - (Forme abrégée : -res) --win32icon:<fichier> Spécifie un fichier d'icône Win32 (.ico) pour les ressources - Win32 par défaut. --win32manifest:<fichier> Le fichier fourni est incorporé dans la - section manifeste du PE de sortie. --win32resource:<fichier> Spécifie un fichier de ressources Win32 (.res). - +-nowin32manifest Le manifeste par défaut ne doit pas être incorporé + dans la section manifeste du PE de sortie. +-resource:<resinfo> Ajoute le fichier spécifié en tant que +incorporé + ressource d’assembly. + resinfo:<file>[,<name>[,public|private]] + (Forme abrégée : -res) +-win32icon:<file> Spécifie un fichier d’icône Win32 (.ico) pour les + ressources Win32 par défaut. +-win32manifest:<file> Le fichier fourni est incorporé dans le manifeste + de la sortie PE. +-win32resource:<file> Spécifie un fichier de ressources Win32 (.res). - GENERATION DE CODE - --optimize [+|-] Active les optimisations. --removeintchecks [+|-] Supprime les contrôles d'entiers. Désactivé par défaut. --debug [+|-] Émet des informations de débogage. --debug:full Émet des informations de débogage complètes (par défaut). --debug:pdbonly Émet des informations de débogage complètes. --debug:portable Émet des informations de débogage multiplateforme. --debug:embedded Émet des informations de débogage multiplateformes dans le - fichier .dll ou .exe cible. --deterministic Produit un assemblage déterministe - (incluant le GUID de la version du module et l'horodatage) --refonly Produit un assemblage de référence à la place de la sortie principale --instrument:TestCoverage Produit un assemblage instrumenté pour collecter des - informations de couverture --sourcelink:<file> Informations sur le lien source à intégrer dans la PDB. + - GÉNÉRATION DE CODE - +-optimize[+|-] Activer les optimisations. +-removeintchecks[+|-] Supprimer les vérifications d’entier. Valeur par défaut désactivée. +-debug[+|-] Émettre des informations de débogage. +-debug:full Émettre des informations de débogage complètes (valeur par défaut). +-debug:pdbonly Émettre des informations de débogage complètes. +-debug:portable Émettre des informations de débogage multiplateforme. +-debug:embedded Émettre des informations de débogage multiplateforme dans + cible .dll ou .exe. +-deterministic Produire un assembly déterministe + (y compris le GUID de version du module et l’horodatage) +-refonly Produire un assembly de référence à la place de la sortie principale +-instrument:TestCoverage Produire un assembly instrumenté pour collecter + les informations de couverture +-sourcelink:<file> Informations de lien source à incorporer dans PDB. - ERREURS ET AVERTISSEMENTS - --nowarn Désactive tous les avertissements. --nowarn:<number_list> Désactiver une liste d'avertissements individuels. --warnaserror[+|-] Traite tous les avertissements comme des erreurs. --warnaserror[+|-]:<number_list> Traite une liste d'avertissements comme des erreurs. --ruleset:<fichier> Spécifier un fichier de jeu de règles qui désactive des - diagnostics spécifiques. --errorlog:<fichier>[,version=<sarif_version>] - Spécifier un fichier pour enregistrer tous les diagnostics du compilateur et de l'analyseur - au format SARIF. - sarif_version:{1|2|2.1} La valeur par défaut est 1. 2 et 2.1 signifient tous deux - la version 2.1.0 de SARIF. --reportanalyzer Signale des informations supplémentaires sur l'analyseur, comme le - temps d'exécution. --skipanalyzers [+|-] Saute l'exécution des analyseurs de diagnostic. +-nowarn Désactivez tous les avertissements. +-nowarn:<number_list> Désactiver une liste d’avertissements individuels. +-warnaserror[+|-] Traitez tous les avertissements comme des erreurs. +-warnaserror[+|-]:<number_list> Traiter une liste d’avertissements comme des erreurs. +-ruleset:<file> Spécifiez un fichier d’ensemble de règles qui désactive des +spécifiques + diagnostics. +-errorlog:<file>[,version=<sarif_version>] + Spécifiez un fichier pour enregistrer tous les +du compilateur et de l’analyseur + diagnostics au format SARIF. + sarif_version :{1|2|2.1} La valeur par défaut est 1. 2 et 2.1 + la version SARIF moyenne 2.1.0. +-reportanalyzer Signaler des informations supplémentaires sur l’analyseur, telles que + durée d’exécution. +-skipanalyzers[+|-] Ignorer l’exécution des analyseurs de diagnostic. - - LANGUAGE - --define:<symbol_list> Déclare un ou plusieurs symboles de compilation conditionnelle globale. - symbol_list:name=value,... + - LANGUE - +-define:<symbol_list> Déclarer des +de compilation conditionnelle globale + symbol(s). symbol_list:name=value,... (Forme abrégée : -d) --imports:<import_list> Déclarer des importations globales pour les espaces de noms dans - fichiers de métadonnées référencés. - import_list:namespace,... +-imports:<import_list> Déclarer des importations globales pour les espaces de noms dans + fichiers de métadonnées référencés. + import_list:namespace,... -langversion:? Afficher les valeurs autorisées pour la version de langue --langversion:<string> Spécifier une version de langue telle que - 'default' (dernière version majeure) ou - 'latest' (dernière version, y compris les versions mineures), - ou des versions spécifiques telles que '14' ou '15.3' --optionexplicit[+|-] Exiger déclaration explicite des variables. --optioninfer[+|-] Autoriser l’inférence de type des variables. --rootnamespace:<string> Spécifie l’espace de noms racine pour toutes les déclarations de type - . --optionstrict[+|-] Appliquer une sémantique de langage stricte. --optionstrict:custom Warn lorsque la sémantique de langage stricte n’est pas - respectée. --optioncompare:binary spécifie des comparaisons de chaînes de style binaire. +-langversion:<string> Spécifier une version de langage telle que + 'default' (dernière version majeure) ou + 'latest' (dernière version, y compris les versions mineures), + ou des versions spécifiques telles que « 14 » ou « 15.3 » +-optionexplicit[+|-] Exiger une déclaration explicite des variables. +-optioninfer[+|-] Autoriser l’inférence de type des variables. +-rootnamespace:<string> Spécifie l’espace de noms racine pour tous les types + Déclarations. +-optionstrict[+|-] Appliquer une sémantique de langage stricte. +-optionstrict:custom Avertir lorsque la sémantique de langage stricte n’est pas + respectée. +-optioncompare:binary Spécifie des comparaisons de chaînes de style binaire. Il s’agit de la valeur par défaut. --optioncompare:text Spécifie des comparaisons de chaînes de style texte. +-optioncompare:text Spécifie des comparaisons de chaînes de style texte. - - DIVERS - --help Afficher ce message d’utilisation. (Forme abrégée : -?) --noconfig N’incluez pas automatiquement VBC. Fichier RSP. --nologo Ne pas afficher la bannière de copyright du compilateur. --quiet Mode de sortie quiet. --verbose Afficher les messages détaillés. --parallel[+|-] Build simultanée. --version Afficher le numéro de version du compilateur et quitter. + - DIVERS - +-help Afficher ce message d’utilisation. (Forme abrégée : -?) +-noconfig N’incluez pas automatiquement VBC. Fichier RSP. +-nologo Ne pas afficher la bannière de copyright du compilateur. +-quiet mode de sortie silencieux. +-verbose Afficher les messages détaillés. +-parallel[+|-] Build simultanée. +-version Afficher le numéro de version du compilateur et quitter. - - AVANCÉ - --baseaddress:<number> Adresse de base d’une bibliothèque ou d’un module - (hexadécimal). --checksumalgorithm:<alg> Spécifiez l’algorithme de calcul du fichier source - somme de contrôle stockée dans PDB. Les valeurs prises en charge sont les suivantes : + - AVANCÉ - +-baseaddress:<number> Adresse de base d’une bibliothèque ou d’un module + (hex). +-checksumalgorithm:<alg> Spécifier l’algorithme de calcul du fichier source + somme de contrôle stockée dans PDB. Les valeurs prises en charge sont les suivantes : SHA1 ou SHA256 (valeur par défaut). --codepage:<number> Spécifie la page de codes à utiliser lors de l’ouverture - fichiers sources. --delaysign[+|-] Signez l’assembly en utilisant uniquement la partie publique - de la clé de nom fort. --publicsign[+|-] Signer publiquement l’assembly en utilisant uniquement la partie publique - de la clé de nom fort. --errorreport:<string> Spécifie comment gérer les erreurs - du compilateur interne ; doit être un - d’invite, d’envoi, aucun ou de file d’attente (par défaut). --filealign:<number> Spécifiez l’alignement utilisé pour les sections - du fichier de sortie. --highentropyva[+|-] Activez L’ASLR à entropie élevée. --keycontainer:<string> Spécifie un conteneur de clé de nom fort. --keyfile:<file> Spécifie un fichier de clé de nom fort. --libpath:<path_list> Liste des répertoires pour rechercher des métadonnées - références. (point-virgule délimité.) --main:<class> Spécifie la classe ou le module qui contient - Sub Main. Il peut également s’agir d’une classe qui - hérite de System.Windows.Forms.Form. +-codepage:<number> Spécifie la page de codes à utiliser lors de l’ouverture de + fichiers sources. +-delaysign[+|-] Signer l’assembly à l’aide du +public uniquement + partie de la clé de nom fort. +-publicsign[+|-] Signature publique de l’assembly à l’aide uniquement de la +publique + partie de la clé de nom fort. +-errorreport:<string> Spécifie comment gérer les +internes du compilateur + Erreurs; doit être un +d’invite, d’envoi, aucun ou de file d’attente + (par défaut). +-generatedfilesout:<dir> Placer les fichiers générés pendant la compilation dans le + répertoire spécifié. +-filealign:<number> Spécifiez l’alignement utilisé pour le fichier de sortie + de sections. +-highentropyva[+|-] Activer ASLR à entropie élevée. +-keycontainer:<string> Spécifie un conteneur de clé de nom fort. +-keyfile:<file> Spécifie un fichier de clé de nom fort. +-libpath:<path_list> Liste des répertoires pour rechercher des métadonnées + références. (Point-virgule délimité.) +-main:<class> Spécifie la classe ou le module qui contient + Sous-principal. Il peut également s’agir d’une classe qui + hérite de System.Windows.Forms.Form. (Forme abrégée : -m) --moduleassemblyname:<string> Nom de l’assembly dont ce module - fait partie. --netcf Ciblez le .NET Compact Framework. --nostdlib Ne référencez pas les bibliothèques standard - (system.dll et VBC. fichier RSP). +-moduleassemblyname:<string> Nom de l’assembly dont ce module + faire partie. +-netcf Cible le .NET Compact Framework. +-nostdlib Ne pas référencer les bibliothèques standard + (system.dll et VBC. fichier RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... Spécifiez un mappage pour la sortie des noms de chemin d’accès source par - le compilateur. --platform:<string> Limitez les plateformes sur lesquelles ce code peut s’exécuter ; - doit être x86, x64, Itanium, arm, arm64 - AnyCPU32BitPreferred ou anycpu (par défaut). --preferreduilang Spécifiez le nom de la langue de sortie par défaut. --nosdkpath Désactivez la recherche dans le chemin d’accès par défaut du SDK pour les assemblys de bibliothèque standard. --sdkpath:<path> Emplacement du répertoire .NET Framework SDK - (mscorlib.dll). --subsystemversion:<version> Spécifiez la version du sous-système de la sortie PE. - version:<number>[.<number>] --utf8output[+|-] Émettre la sortie du compilateur en encodage - caractères UTF-8. -@<file> Insérer des paramètres de ligne de commande à partir d’un fichier texte --vbruntime[+|-|*] Compilez avec/sans le runtime Visual Basic - par défaut. --vbruntime:<file> Compilez avec l’autre runtime Visual Basic - dans <file>. + le compilateur. +-platform:<string> Limitez les plateformes sur lesquelles ce code peut s’exécuter ; + doit être x86, x64, Itanium, arm, arm64 + AnyCPU32BitP référencé ou anycpu (par défaut). +-preferreduilang Spécifiez le nom de la langue de sortie par défaut. +-nosdkpath Désactiver la recherche dans le chemin d’accès par défaut du Kit de développement logiciel (SDK) pour les assemblys de bibliothèque standard. +-sdkpath:<path> Emplacement du répertoire .NET Framework SDK + (mscorlib.dll). +-subsystemversion:<version> Spécifiez la version du sous-système de la sortie PE. + version:<number>[.<number>] +-utf8output[+|-] Émettre la sortie du compilateur en caractères UTF-8 + encodage. +@<file> Insérer des paramètres de ligne de commande à partir d’un fichier texte +-vbruntime[+|-|*] Compiler avec/sans la Visual Basic +par défaut + runtime. +-vbruntime:<file> Compiler avec l’autre Visual Basic + runtime dans <file>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf index 2de080fc922bf..c8c5b9a4270ea 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.it.xlf @@ -269,54 +269,54 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Opzioni del compilatore Visual Basic + Opzioni del compilatore Visual Basic - FILE DI OUTPUT - --out:<file> Specifica il nome del file di output. +-out:<file> Consente di specificare il nome del file di output. -target:exe Crea un'applicazione console (impostazione predefinita). - (Forma breve: -t) + Forma breve: -t -target:winexe Crea un'applicazione Windows. -target:library Crea un assembly di librerie. -target:module Crea un modulo che può essere aggiunto a un assembly. -target:appcontainerexe Crea un'applicazione Windows che viene eseguita in AppContainer. --target:winmdobj Crea un file intermedio di metadati di Windows +-target:winmdobj Crea file intermedio di metadati di Windows -doc[+|-] Genera un file di documentazione XML. -doc:<file> Genera un file di documentazione XML in <file>. -refout:<file> Output dell'assembly di riferimento da generare - FILE DI INPUT - --addmodule:<elenco_file> Crea un riferimento ai metadati dai moduli specificati --link:<elenco_file> Incorpora metadati dall'assembly di interoperabilità - specificato. (Forma breve: -l) --recurse:<caratteri_jolly> Include tutti i file presenti nella directory corrente - e nelle relative sottodirectory in base - ai caratteri jolly specificati. --reference:<elenco_file> Crea un riferimento ai metadati dall'assembly - specificato. (Forma breve: -r) --analyzer:<elenco_file> Esegue gli analizzatori dall'assembly - (Forma breve: -a) --additionalfile:<elenco file> File aggiuntivi che non influiscono - direttamente sulla generazione del codice ma possono essere usati - dagli analizzatori per produrre errori o avvisi. +-addmodule:<file_list> Crea un riferimento ai metadati dai moduli specificati +-link:<file_list> Incorpora metadati dall'assembly di interoperabilità + specificato. Forma breve: -l +-recurse:<wildcard> Include tutti i file presenti nella directory corrente + e nelle relative sottodirectory in base ai + caratteri jolly specificati. +-reference:<file_list> Crea un riferimento ai metadati dal file di assembly + specificato. Forma breve: -r +-analyzer:<file_list> Esegue gli analizzatori dall'assembly + Forma breve: -a +-additionalfile:<file list> File aggiuntivi che non influiscono direttamente sulla generazione + del codice ma possono essere usati dagli analizzatori per produrre + errori o avvisi. - RISORSE - --linkresource:<info_risorsa> Collega il file specificato come +-linkresource:<resinfo> Collega il file specificato come risorsa di assembly esterna. - resinfo:<file>[,<nome>[,public|private]] - (Forma breve: -linkres) + resinfo:<file>[,<name>[,public|private]] + Forma breve: -linkres -nowin32manifest Il manifesto predefinito non deve essere incorporato nella sezione manifesto del file PE di output. --resource:<info_risorsa> Aggiunge il file specificato come +-resource:<resinfo> Aggiunge il file specificato come risorsa di assembly incorporata. - resinfo:<file>[,<nome>[,public|private]] - (Forma breve: -res) --win32icon:<file> Specifica un file di icona Win32 (.ico) per le risorse + resinfo:<file>[,<name>[,public|private]] + Forma breve: -res +-win32icon:<file> Consente di specificare un file di icona Win32 (.ico) per le risorse Win32 predefinite. -win32manifest:<file> Il file fornito è incorporato nella sezione manifesto del file PE di output. --win32resource:<file> Specifica un file di risorse Win32 (.res). +-win32resource:<file> Consente di specificare un file di risorse Win32 (.res). - GENERAZIONE DEL CODICE - -optimize[+|-] Abilita le ottimizzazioni. @@ -336,46 +336,46 @@ - ERRORI E AVVISI - -nowarn Disabilita tutti gli avvisi. --nowarn:<elenco_numeri> Disabilita un elenco di avvisi singoli. +-nowarn:<number_list> Disabilita un elenco di avvisi singoli. -warnaserror[+|-] Considera tutti gli avvisi come errori. --warnaserror[+|-]:<elenco_numeri> Considera un elenco di avvisi come errori. --ruleset:<file> Specifica un file di set di regole che disabilita una +-warnaserror[+|-]:<number_list> Considera un elenco di avvisi come errori. +-ruleset:<file> Consente di specificare un file di set di regole che disabilita diagnostica specifica. --errorlog:<file>[,version=<versione _SARIF>] - Specifica un file in cui registrare tutte le diagnostiche del +-errorlog:<file>[,version=<sarif_version>] + Consente di specificare un file in cui registrare tutte le diagnostiche del compilatore e dell'analizzatore in formato SARIF. sarif_version:{1|2|2.1} L'impostazione predefinita è 1. 2 e 2.1 si riferiscono entrambi a SARIF versione 2.1.0. -reportanalyzer Restituisce informazioni aggiuntive dell'analizzatore, ad esempio il tempo di esecuzione. --skipanalyzers[+|-] Ignora l'esecuzione degli analizzatori diagnostici. +-skipanalyzers[+|-] Ignora l'esecuzione degli analizzatore diagnostici. - LINGUAGGIO - --define:<elenco_simboli> Dichiara simboli di compilazione condizionale - globale. symbol_list:name=value,... - (Forma breve: -d) --imports:<elenco_importazioni> Dichiara importazioni globali per spazi dei nomi in +-define:<symbol_list> Dichiara simboli di compilazione + condizionale. symbol_list:name=value,... + Forma breve: -d +-imports:<import_list> Dichiara importazioni globali per spazi dei nomi in file di metadati a cui viene fatto riferimento. import_list:namespace,... -langversion:? Visualizza i valori consentiti per la versione del linguaggio --langversion:<stringa> Specifica la versione del linguaggio, ad esempio - `default` (ultima versione principale) o - `latest` (ultima versione che include versioni secondarie) - oppure versioni specifiche, come `14` o `15.3` +-langversion:<string> Consente di specificare la versione del linguaggio, ad esempio + 'default' (ultima versione principale) o + 'latest' (ultima versione che include versioni secondarie) + o versioni specifiche come '14' o '15.3' -optionexplicit[+|-] Richiede la dichiarazione esplicita delle variabili. -optioninfer[+|-] Consente l'inferenza del tipo delle variabili. --rootnamespace:<stringa> Specifica lo spazio dei nomi radice per tutte le dichiarazioni +-rootnamespace:<string> Consente di specificare lo spazio dei nomi radice per tutte le dichiarazioni di tipo. -optionstrict[+|-] Attiva la semantica del linguaggio strict. -optionstrict:custom Avvisa quando la semantica del linguaggio strict non viene rispettata. --optioncompare:binary Specifica i confronti fra stringhe binarie. +-optioncompare:binary Consente di specificare i confronti fra stringhe binarie. Impostazione predefinita. --optioncompare:text Specifica i confronti fra stringhe di testo. +-optioncompare:text Consente di specificare i confronti fra stringhe di testo. - VARIE - --help Visualizza questo messaggio relativo alla sintassi. (Forma breve: -?) --noconfig Non include automaticamente il file VBC.RSP file. +-help Visualizza questo messaggio relativo alla sintassi. Forma breve: -? +-noconfig Non include automaticamente il file VBC.RSP. -nologo Non visualizza le informazioni sul copyright del compilatore. -quiet Modalità di output non interattiva. -verbose Visualizza messaggi dettagliati. @@ -383,51 +383,53 @@ -version Visualizza il numero di versione del compilatore ed esce. - AVANZATE - --baseaddress:<numero> Indirizzo di base di una libreria o di un modulo +-baseaddress:<number> Indirizzo di base di una libreria o di un modulo (hex). --checksumalgorithm:<alg> Specifica l'algoritmo per calcolare il checksum +-checksumalgorithm:<alg> Consente di specificare l'algoritmo per calcolare il checksum del file di origine archiviato nel file PDB. I valori supportati sono: SHA1 o SHA256 (impostazione predefinita). --codepage:<numero> Specifica la tabella codici da usare all'apertura dei file +-codepage:<number> Consente di specificare la tabella codici da usare all'apertura dei file di origine. -delaysign[+|-] Ritarda la firma dell'assembly usando solo la parte pubblica della chiave con nome sicuro. -publicsign[+|-] Firma pubblicamente l'assembly usando solo la parte pubblica della chiave con nome sicuro. --errorreport:<stringa> Specifica come gestire gli errori interni del compilatore. +-errorreport:<string> Consente di specificare come gestire gli errori interni del compilatore. I valori devono essere prompt, send, none o queue (impostazione predefinita). --filealign:<numero> Specifica l'allineamento usato per le sezioni del file di - output. +-generatedfilesout:<dir> Inserisce i file generati durante la compilazione nella + directory specificata. +-filealign:<number> Consente di specificare l'allineamento usato per le sezioni del + file di output. -highentropyva[+|-] Abilita ASLR a entropia elevata. --keycontainer:<stringa> Specifica un contenitore di chiavi con nome sicuro. --keyfile:<file> Specifica un file di chiave con nome sicuro. --libpath:<elenco_percorsi> Elenco di directory delimitate da punti e virgola in cui cercare - riferimenti ai metadati. --main:<classe> Specifica la classe o il modulo che contiene +-keycontainer:<string> Consente di specificare un contenitore di chiavi con nome sicuro. +-keyfile:<file> Consente di specificare un file di chiave con nome sicuro. +-libpath:<path_list> Elenco di directory in cui cercare + riferimenti ai metadati. (Delimitato da punto e virgola). +-main:<class> Consente di specificare la classe o il modulo che contiene Sub Main. Può essere anche una classe che eredita da System.Windows.Forms.Form. - (Forma breve: -m) --moduleassemblyname:<stringa> Nome dell'assembly di cui farà parte questo + Forma breve: -m +-moduleassemblyname:<string> Nome dell'assembly di cui farà parte questo modulo. -netcf Destinato a .NET Compact Framework. -nostdlib Omette i riferimenti alle librerie standard - (file system.dll e VBC.RSP). + (file system.dll eVBC.RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... - Specifica un mapping per i nomi di percorso di origine + Consente di specificare un mapping per i nomi di percorso di origine visualizzati dal compilatore. --platform:<stringa> Limita le piattaforme in cui è possibile eseguire questo codice. - Il valore deve essere x86, x64, Itanium, arm, arm64, +-platform:<string> Limita le piattaforme in cui è possibile eseguire questo codice. + Il valore deve essere x86, x64, Itanium, arm, arm64 AnyCPU32BitPreferred o anycpu (impostazione predefinita). --preferreduilang Specifica il nome del linguaggio di output preferito. +-preferreduilang Consente di specificare il nome del linguaggio di output preferito. -nosdkpath Disabilita la ricerca di assembly di librerie standard nel percorso predefinito dell'SDK. --sdkpath:<percorso> Percorso della directory di .NET Framework SDK +-sdkpath:<path> Percorso della directory di .NET Framework SDK (mscorlib.dll). --subsystemversion:<versione> Specifica la versione del sottosistema del file PE di output. - version:<numero>[.<numero>] +-subsystemversion:<version> Consente di specificare la versione del sottosistema del file PE di output. + version:<number>[.<number>] -utf8output[+|-] Crea l'output del compilatore con codifica dei caratteri UTF8. -@<file> Inserisce le impostazioni della riga di comando da un file di testo. +@<file> Inserisce le impostazioni della riga di comando da un file di testo -vbruntime[+|-|*] Compila con/senza il runtime di Visual Basic predefinito. -vbruntime:<file> Compila con il runtime di Visual Basic alternativo diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index d359507af6055..5919d133d020b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -269,169 +269,200 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Visual Basic コンパイラ オプション + Visual Basic コンパイラ オプション - - 出力ファイル - + - 出力ファイル - -out:<file> 出力ファイル名を指定します。 --target:exe コンソール アプリケーションを作成します (デフォルト)。 - (短縮形: -t) +-target:exe コンソール アプリケーション (既定)を作成します。 + (短い形式: -t) -target:winexe Windows アプリケーションを作成します。 -target:library ライブラリ アセンブリを作成します。 --target:module アセンブリに追加できるモジュールを作成します。 - --target:appcontainerexe AppContainer で実行される Windows アプリケーション - を作成します。 --target:winmdobj Windows メタデータ中間ファイルを作成します。 +-target:module +に追加できるモジュールを作成する + アセンブリ。 +-target:appcontainerexe +で実行される Windows アプリケーションを作成する + AppContainer。 +-target:winmdobj Windows メタデータ中間ファイル +の作成 -doc[+|-] XML ドキュメント ファイルを生成します。 -doc:<file> <file> に XML ドキュメント ファイルを生成します。 --refout:<file> 生成する参照アセンブリ出力を指定します。 +-refout:<file> アセンブリ出力を参照して +を生成します - - 入力ファイル - --addmodule:<file_list> 指定したモジュールからメタデータを参照します。 --link:<file_list> 指定した相互運用アセンブリからメタデータを - 埋め込みます。(短縮形: -l) --recurse:<wildcard> 現在のディレクトリ - およびサブディレクトリ内のすべてのファイルを、 - ワイルドカードの指定に従って含めます。 --reference:<file_list> 指定したアセンブリからメタデータを - 参照します。(短縮形: -r) --analyzer:<file_list> このアセンブリからアナライザーを実行します。 - (短縮形: -a) --additionalfile:<file list> アナライザーがエラーや警告を生成するのに使う - (コード生成に直接影響しない) 追加ファイルを - 指定します。 + - 入力ファイル - +-addmodule:<file_list> 指定されたモジュールからの参照メタデータ +-link:<file_list> 指定された相互運用機能からメタデータの埋め込み + アセンブリ。(短い形式: -l) +-recurse:<wildcard> 現在のディレクトリ内のすべてのファイルを含める + と + に従ったサブディレクトリ + ワイルドカードの指定。 +-reference:<file_list> 指定した +からの参照メタデータ + アセンブリ。(短い形式: -r) +-analyzer:<file_list> このアセンブリからアナライザーを実行 + (短い形式: -a) +-additionalfile:<file list> コード +に直接影響しない追加ファイル + 生成しますが、アナライザーで +を生成するために使用できます + エラーまたは警告。 - - リソース - --linkresource:<resinfo> 指定したファイルを外部アセンブリ リソースとして - リンクします。 - resinfo:<file>[,<name>[,public|private]] - (短縮形: -linkres) --nowin32manifest デフォルトのマニフェストを出力 PE のマニフェスト - セクションに埋め込まないようにします。 + - リソース - +-linkresource:<resinfo> 指定したファイルを外部 +としてリンクします + アセンブリ リソース。 + resinfo:<file>[,<name>[,public|private]] + (短い形式: -linkres) +-nowin32manifest 既定のマニフェストを埋め込むべきではありません + 出力 PE のマニフェスト セクションに。 -resource:<resinfo> 指定したファイルを埋め込み - アセンブリ リソースとして追加します。 - resinfo:<file>[,<name>[,public|private]] - (短縮形: -res) --win32icon:<file> デフォルトの Win32 リソースとして Win32 アイコン - ファイル (.ico) を指定します。 --win32manifest:<file> 指定したファイルを出力 PE のマニフェスト - セクションに埋め込みます。 +として追加します + アセンブリ リソース。 + resinfo:<file>[,<name>[,public|private]] + (短い形式: -res) +-win32icon:<file> +の Win32 アイコン ファイル (.ico) を指定します + 既定の Win32 リソース。 +-win32manifest:<file> 指定されたファイルはマニフェスト +に埋め込まれています + 出力 PE のセクション。 -win32resource:<file> Win32 リソース ファイル (.res) を指定します。 - - コード生成 - + - コード生成 - -optimize[+|-] 最適化を有効にします。 --removeintchecks[+|-] integer チェックを省きます。デフォルトはオフです。 +-removeintchecks[+|-] 整数チェックを削除します。既定値はオフです。 -debug[+|-] デバッグ情報を出力します。 --debug:full すべてのデバッグ情報を出力します (デフォルト)。 --debug:pdbonly すべてのデバッグ情報を出力します。 --debug:portable クロス プラットフォームのデバッグ情報を出力します。 --debug:embedded クロス プラットフォームのデバッグ情報をターゲットの - .dll または .exe に出力します。 --deterministic 決定的なアセンブリを出力します。 - (モジュール バージョンの GUID とタイムスタンプを含む) --refonly 本来の出力の代わりに参照アセンブリを出力します。 --instrument:TestCoverage カバレッジ情報の収集命令のあるアセンブリを - 出力します。 +-debug:full 完全なデバッグ情報を出力します (既定)。 +-debug:pdbonly 完全なデバッグ情報を出力します。 +-debug:portable クロスプラットフォーム デバッグ情報を出力します。 +-debug:embedded クロスプラットフォーム デバッグ情報を + に出力する + ターゲット .dll または .exe。 +-deterministic 決定論的アセンブリ +を生成する + (モジュール バージョン GUID とタイムスタンプを含む) +-refonly メイン出力 +の代わりに参照アセンブリを生成する +-instrument:TestCoverage + を収集するようにインストルメント化されたアセンブリを生成する + カバレッジ情報 -sourcelink:<file> PDB に埋め込むソース リンク情報。 - - エラーと警告 - --nowarn すべての警告を抑止します。 --nowarn:<number_list> リストで指定された警告を抑止します。 + - エラーと警告 - +-nowarn すべての警告を無効にします。 +-nowarn:<number_list> 個々の警告の一覧を無効にします。 -warnaserror[+|-] すべての警告をエラーとして扱います。 --warnaserror[+|-]:<number_list> リストで指定された警告をエラーとして扱います。 --ruleset:<file> 特定の診断を抑止するルールセット ファイル - を指定します。 +-warnaserror[+|-]: <number_list> 警告の一覧をエラーとして扱います。 +-ruleset:<file> 特定の +を無効にするルールセット ファイルを指定します + 診断。 -errorlog:<file>[,version=<sarif_version>] - コンパイラとアナライザーのすべての診断を SARIF 形式で - ログ出力するファイルを指定します。 - sarif_version:{1|2|2.1} デフォルトは 1. 2 と 2.1 - 両方とも SARIF バージョン 2.1.0 を意味します。 --reportanalyzer 実行時間などの追加のアナライザー情報を - レポートします。 + すべてのコンパイラとアナライザーをログに記録するファイルの指定 + SARIF 形式の診断。 + sarif_version:{1|2|2.1} 既定値は 1. 2 と 2.1 + 両方とも SARIF バージョン 2.1.0 を意味します +-reportanalyzer レポート +などの追加のアナライザー情報 + 実行時間。 -skipanalyzers[+|-] 診断アナライザーの実行をスキップします。 - - 言語 - --define:<symbol_list> グローバルな条件付きコンパイル シンボルを - 宣言します。symbol_list:name=値,... - (短縮形: -d) --imports:<import_list> 参照先のメタデータ ファイルの名前空間へのグローバルな - インポートを宣言します。 - import_list:名前空間,... --langversion:? 言語バージョンに使用できる値を表示します。 --langversion:<string> 言語バージョンとして - `default` (最新のメジャー バージョン)、 - `latest` (マイナー バージョンを含む最新のバージョン)、 - `14` や `15.3` などの特定のバージョンを指定します。 --optionexplicit[+|-] 変数の明示的な宣言を必須とします。 --optioninfer[+|-] 変数の型推定を有効にします。 --rootnamespace:<string> すべての型宣言のルートの名前空間を - 指定します。 --optionstrict[+|-] 厳格な言語セマンティクスを適用します。 --optionstrict:custom 厳密な言語セマンティクスから外れる場合に - 警告します。 + - 言語 - +-define:<symbol_list> グローバル条件付きコンパイルを宣言する + シンボル。symbol_list:name=value,... + (短い形式: -d) +-imports:<import_list> +で名前空間のグローバル インポートを宣言する + 参照されたメタデータ ファイル。 + import_list:namespace,... +-langversion:? 言語バージョン +で使用できる値を表示する +-langversion:<string> +などの言語バージョンを指定します + 'default' (最新のメジャー バージョン)、または + 'latest' (マイナー バージョンを含む最新バージョン) + または `14` や `15.3` などの特定のバージョン +-optionexplicit[+|-] 変数の明示的な宣言が必要です。 +-optioninfer[+|-] 変数の型推論を許可します。 +-rootnamespace:<string> すべての型のルート名前空間を指定 + 宣言。 +-optionstrict[+|-] 厳密な言語セマンティクスを適用します。 +-optionstrict:custom 厳密な言語セマンティクスが +でない場合の警告 + 尊敬される。 -optioncompare:binary バイナリ スタイルの文字列比較を指定します。 - これがデフォルトです。 + これは既定です。 -optioncompare:text テキスト スタイルの文字列比較を指定します。 - - その他 - --help このヘルプメッセージを表示します。(短縮形: -?) --noconfig VBC.RSP ファイルをオート インクルードしません。 + - その他 - +-help この使用状況メッセージを表示します。(短い形式: -?) +-noconfig VBC.RSP ファイルを自動インクルードしないでください。 -nologo コンパイラの著作権バナーを表示しません。 --quiet 何も表示しません。 +-quiet 非表示出力モード。 -verbose 詳細メッセージを表示します。 --parallel[+|-] コンカレント ビルド。 --version コンパイラ のバージョン番号を表紙して終了します。 +-parallel[+|-] 同時ビルド。 +-version コンパイラのバージョン番号を表示して終了します。 - - 詳細 - --baseaddress:<number> ライブラリまたはモジュールのベースアドレス - (16 進数). --checksumalgorithm:<alg> PDB に保存するソース ファイルのチェックサム計算 - アルゴリズムを指定します。サポートされている値: - SHA1 または SHA256 (デフォルト). --codepage:<number> ソース ファイルを開くときに使用するコード ページ - を指定します。 --delaysign[+|-] 厳密な名前キーのパブリック 部分のみを使用して - アセンブリに遅延署名します。 --publicsign[+|-] 厳密な名前キーのパブリック 部分のみを使用して - アセンブリに公開署名します。 --errorreport:<string> 内部コンパイラ エラーを処理する方法を - 指定します。値は次のいずれか: prompt, send, none, queue - (デフォルト) --filealign:<number> 出力ファイルのセクションに使用する配置を - 指定します。 + - 詳細設定 - +-baseaddress:<number> ライブラリまたはモジュールのベース アドレス + (16 進数)。 +-checksumalgorithm:<alg> ソース ファイル +を計算するためのアルゴリズムを指定します + PDB に格納されているチェックサム。サポートされている値: + SHA1 または SHA256 (既定値)。 +-codepage:<number> +を開くときに使用するコードページを指定します。 + ソース ファイル。 +-delaysign[+|-] パブリックのみを使用してアセンブリに遅延署名する + 厳密な名前キーの部分。 +-publicsign[+|-] パブリックのみを使用してアセンブリに公開署名する + 厳密な名前キーの部分。 +-errorreport:<string> 内部コンパイラを処理する方法を指定します + エラー; プロンプト、送信、なし、またはキューである必要があります + (既定値)。 +-generatedfilesout:<dir> コンパイル中に生成されたファイルを +に配置します + 指定したディレクトリ。 +-filealign:<number> 出力ファイルに使用する配置を指定します + セクション。 -highentropyva[+|-] 高エントロピ ASLR を有効にします。 -keycontainer:<string> 厳密な名前のキー コンテナーを指定します。 --keyfile:<file> 厳密な名前のキー ファイルを指定します。 --libpath:<path_list> メタデータ参照を検索するディレクトリの - 一覧です。(セミコロン区切り) --main:<class> Sub Main を含むクラスまたはモジュールを - .指定します。System.Windows.Forms.Form からの - 継承クラスにすることもできます。 - (短縮形: -m) --moduleassemblyname:<string> このモジュールが含まれる - アセンブリの名前 。 --netcf .NET Compact Framework を対象とします。 --nostdlib 標準ライブラリ (system.dll と VBC.RSP ファイル) - を参照しません。 +-keyfile:<file> 厳密な名前のキー ファイルを指定します。 +-libpath:<path_list> メタデータを検索するディレクトリの一覧 + 参照。(セミコロン区切り)。 +-main:<class> +を含むクラスまたはモジュールを指定します。 + サブ メイン。また、 +というクラスにすることもできます。 + System.Windows.Forms.Form から継承します。 + (短い形式: -m) +-moduleassemblyname:<string> このモジュールが +するアセンブリの名前 + の一部です。 +-netcf .NET Compact Frameworkをターゲットに設定します。 +-nostdlib 標準ライブラリを参照しない + (system.dll と VBC.RSP ファイル)。 -pathmap:<K1>=<V1>,<K2>=<V2>,... - ソースのパス名についてコンパイラが出力するマッピングを - 指定します。 --platform:<string> このコードを実行できるプラットフォームを限定します。 - 値は次のいずれか: x86, x64, Itanium, arm, arm64 - AnyCPU32BitPreferred, anycpu (デフォルト). --preferreduilang 優先して出力する言語名を指定します。 + +で出力されるソース パス名のマッピングを指定する + コンパイラ。 +-platform:<string> このコードを実行できるプラットフォームを制限します; + x86, x64, Itanium, arm, arm64 である必要があります + AnyCPU32BitPreferred または anycpu (既定値)。 +-preferreduilang 優先する出力言語名を指定します。 -nosdkpath 標準ライブラリ アセンブリの既定の SDK パスの検索を無効にします。 --sdkpath:<path> .NET Framework SDK ディレクトリ の場所。 - (mscorlib.dll). +-sdkpath:<path> .NET Framework SDK ディレクトリの場所 + (mscorlib.dll)。 -subsystemversion:<version> 出力 PE のサブシステム バージョンを指定します。 - version:<number>[.<number>] --utf8output[+|-] コンパイラの出力を UTF-8 文字エンコード - にします。 -@<file> コマンド ライン設定をテキスト ファイルから挿入します。 --vbruntime[+|-|*] 既定の Visual Basic ランタイムを使用して/使用せずに - コンパイルします。 --vbruntime:<file> Visual Basic ランタイムとして <file> を代わりに使用して - コンパイルします。 + version:<number>[.<number>] +-utf8output[+|-] UTF-8 文字でコンパイラ出力を出力する + エンコード。 +@<file> テキスト ファイルからコマンド ライン設定を挿入 +-vbruntime[+|-|*] 既定の Visual Basic の有無にかかわらずコンパイルする + ランタイム。 +-vbruntime:<file> 代替 Visual Basic を使用してコンパイルする + <file> のランタイム。 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf index 80b9010a7f555..9124adc5e964a 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ko.xlf @@ -269,168 +269,170 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Visual Basic 컴파일러 옵션 + Visual Basic 컴파일러 옵션 - - OUTPUT FILE - --out:<file> 출력 파일 이름을 지정합니다. --target:exe 콘솔 애플리케이션을 만듭니다(기본값). + - 출력 파일 - +-out:<file> 출력 파일 이름을 지정합니다. +-target:exe 콘솔 애플리케이션을 만듭니다(기본값). (약식: -t) --target:winexe Windows 응용 프로그램을 만듭니다. --target:library 라이브러리 어셈블리를 만듭니다. --target:module 어셈블리에 추가할 수 있는 모듈을 +-target:winexe Windows 애플리케이션을 만듭니다. +-target:library 라이브러리 어셈블리를 만듭니다. +-target:module 어셈블리에 추가할 수 있는 모듈을 만듭니다. --target:appcontainerexe AppContainer에서 실행되는 Windows 애플리케이션을 +-target:appcontainerexe AppContainer에서 실행되는 Windows 애플리케이션을 만듭니다. --target:winmdobj Windows 메타데이터 중간 파일을 만듭니다 --doc[+|-] XML 문서 파일을 생성합니다. --doc:<file> <file>에 XML 문서 파일을 생성합니다. --refout:<file> 생성할 참조 어셈블리 출력 +-target:winmdobj Windows 메타데이터 중간 파일을 만듭니다. +-doc[+|-] XML 문서 파일을 생성합니다. +-doc:<file> XML 문서 파일을 <file>(으)로 생성합니다. +-refout:<file> 다음을 생성하기 위한 참조 어셈블리 - - INPUT FILES - --addmodule:<file_list> 지정된 모듈의 참조 메타데이터 --link:<file_list> 지정된 interop 어셈블리의 메타데이터를 - 포함합니다. (약식: -l) --recurse:<wildcard> 와일드카드 사양에 따라 - 현재 디렉터리와 하위 디렉터리의 - 모든 파일을 포함합니다. --reference:<file_list> 지정된 어셈블리의 메타데이터를 + - 입력 파일 - +-addmodule:<file_list> 지정된 모듈의 참조 메타데이터 +-link:<file_list> 지정한 interop 어셈블리의 메타데이터를 + 참조합니다. (약식: -l) +-recurse:<wildcard> 현재 디렉터리 + 및 하위 디렉터리의 모든 파일을 + 와일드카드 사양에 따라 포함합니다. +-reference:<file_list> 지정한 어셈블리 파일에서 메타데이터를 참조합니다. (약식: -r) --analyzer:<file_list> 이 어셈블리에서 분석기를 실행합니다 +-analyzer:<file_list> 이 어셈블리에서 분석기 실행 (약식: -a) --additionalfile:<file list> 코드 생성에 직접적인 영향을 미치지 않지만 - 오류 또는 경고를 생성하기 위해 분석기가 - 사용할 수 있는 추가 파일입니다. +-additionalfile:<file list> 코드 생성에 직접 영향을 주지 않지만 + 오류 경고를 생성하기 위해 분석기에 사용되는 + 추가 파일입니다. - - RESOURCES - --linkresource:<resinfo> 지정된 파일을 외부 어셈블리 - 리소스로 연결합니다. + - 리소스 - +-linkresource:<resinfo> 지정된 파일을 외부 어셈블리 리소스로 파일을 + 추가합니다. resinfo:<file>[,<name>[,public|private]] (약식: -linkres) --nowin32manifest 기본 매니페스트는 출력 PE의 매니페스트 섹션에 - 포함되어서는 안 됩니다. --resource:<resinfo> 지정된 파일을 포함된 어셈블리 - 리소스로 추가합니다. +-nowin32manifest 기본 매니페스트를 출력 PE의 매니페스트 섹션에 + 포함시키면 안됩니다. +-resource:<resinfo> 지정된 파일을 어셈블리 리소스로 + 추가합니다. resinfo:<file>[,<name>[,public|private]] (약식: -res) --win32icon:<file> 기본 Win32 리소스에 대한 - Win32 아이콘 파일(.ico)을 지정합니다. --win32manifest:<file> 제공된 파일은 출력 PE의 매니페스트 - 섹션에 포함됩니다. --win32resource:<file> Win32 리소스 파일(.res)을 지정합니다. +-win32icon:<file> 기본 Win32 리소스용 Win32 아이콘 파일(.ico)을 + 지정합니다. +-win32manifest:<file> 제공된 파일이 출력 PE의 매니페스트 + 섹션에 포함되었습니다. +-win32resource:<file> Win32 리소스 파일(.res)을 지정합니다. - - CODE GENERATION - --optimize[+|-] 최적화를 활성화합니다. --removeintchecks[+|-] 정수 검사를 제거합니다. 기본값 꺼짐. --debug[+|-] 디버깅 정보를 내보냅니다. --debug:full 전체 디버깅 정보를 내보냅니다(기본값). --debug:pdbonly 전체 디버깅 정보를 내보냅니다. --debug:portable 플랫폼 간 디버깅 정보를 내보냅니다. --debug:embedded 플랫폼 간 디버깅 정보를 대상 - .dll 또는 .exe로 내보냅니다. --deterministic 결정적 어셈블리를 생성합니다 + - 코드 생성 - +-optimize[+|-] 최적화를 사용하도록 설정합니다. +-removeintchecks[+|-] 정수 검사를 제거합니다. 기본값을 해제합니다. +-debug[+|-] 디버깅 정보를 내보냅니다. +-debug:full 전체 디버깅 정보를 내보냅니다(기본값). +-debug:pdbonly 전체 디버깅 정보를 내보냅니다. +-debug:portable Emit 플랫폼 간 디버깅 정보를 내보냅니다. +-debug:embedded 플랫폼 간 디버깅 정보를 + 대상 .dll 또는 .exe로 내보냅니다. +-deterministic 결정적 어셈블리 생성 (모듈 버전 GUID 및 타임스탬프 포함) --refonly 주 출력 대신 참조 어셈블리를 생성합니다 --instrument:TestCoverage 적용 범위 정보를 수집하도록 계측된 - 어셈블리를 생성합니다 --sourcelink:<file> PDB에 포함할 원본 링크 정보입니다. +-refonly 주 출력 대신 참조 어셈블리 생성 +-instrument:TestCoverage 검사 정보를 수집하도록 사용될 + 어셈블리 생성 +-sourcelink:<file> PDB에 포함할 원본 링크 정보입니다. - - ERRORS AND WARNINGS - --nowarn 모든 경고를 비활성화합니다. --nowarn:<number_list> 개별 경고 목록을 비활성화합니다. --warnaserror[+|-] 모든 경고를 오류로 처리하세요. --warnaserror[+|-]:<number_list> 경고 목록을 오류로 취급합니다. --ruleset:<file> 특정 진단을 비활성화하는 규칙 - 집합 파일을 지정하세요. + - 오류 및 경고 - +-nowarn 모든 경고를 사용하지 않도록 설정합니다. +-nowarn:<number_list> 개별 경고 목록을 사용하지 않도록 설정합니다. +-warnaserror[+|-] 모든 경고를 오류로 처리합니다. +-warnaserror[+|-]:<number_list> 경고 목록을 오류로 처리합니다. +-ruleset:<file> 특정 진단을 사용하지 않도록 설정하는 규칙 집합 파일을 + 지정합니다. -errorlog:<file>[,version=<sarif_version>] - 모든 컴파일러 및 분석기 진단을 SARIF 형식으로 - 기록할 파일을 지정하세요. - sarif_version:{1|2|2.1} Default is 1. 2 and 2.1 + 모든 컴파일러 및 분석기의 진단을 SARIF 형식으로 기록하기 위해 + 파일을 지정합니다. + sarif_version:{1|2|2.1} 기본값은 1. 2과 2.1이며 둘 다 SARIF 버전 2.1.0을 의미합니다. --reportanalyzer 실행 시간과 같은 추가 분석기 - 정보를 보고합니다. --skipanalyzers[+|-] 진단 분석기의 실행을 건너뜁니다. +-reportanalyzer 실행 시간과 같은 추가 분석기 정보를 + 보고합니다. +-skipanalyzers[+|-] 진단 분석기 실행을 건너뜁니다. - - LANGUAGE - --define:<symbol_list> 전역 조건부 컴파일 기호를 - 선언합니다. symbol_list:name=value,... + -언어- +-define:<symbol_list> 전역 조건부 컴파일 기호를 선언합니다. + symbol_list:name=value,... (약식: -d) --imports:<import_list> 참조된 메타데이터 파일의 네임스페이스에 대해 +-imports:<import_list> 참조한 메타데이터 파일의 네임스페이스에 대해 전역 가져오기를 선언합니다. import_list:namespace,... -langversion:? 언어 버전에 허용되는 값을 표시합니다. --langversion:<string> `default`(최신 주 버전) 또는 - `latest`(최신 버전, 부 버전 포함)와 같은 - 언어 버전이나 `14` 또는 `15.3`과 같은 - 특정 버전을 지정합니다. --optionexplicit[+|-] 변수의 명시적 선언이 필요합니다. --optioninfer[+|-] 변수의 유형 추론을 허용합니다. --rootnamespace:<string> 모든 유형 선언에 대한 루트 - 네임스페이스를 지정합니다. --optionstrict[+|-] 엄격한 언어 의미를 적용합니다. --optionstrict:custom 엄격한 언어 의미가 존중되지 않을 때 +-langversion:<string> 다음과 같이 언어 버전을 지정합니다. + 'default'(최신 주 버전), 또는 + 'latest'(부 버전을 포함한 최신 버전), + 또는 특정 버전(예: '14' 또는 '15.3') +-optionexplicit[+|-] 변수의 명시적 선언이 필요합니다. +-optioninfer[+|-] 변수의 형식 유추를 허용합니다. +-rootnamespace:<string> 모든 형식 선언에 대한 루트 네임스페이스를 + 지정합니다. +-optionstrict[+|-] 언어 의미 체계를 엄격하게 확인합니다. +-optionstrict:custom 엄격한 언어 의미 체계를 준수하지 않을 경우 경고합니다. --optioncompare:binary 바이너리 스타일 문자열 비교를 지정합니다. - 기본값입니다. --optioncompare:text 텍스트 스타일 문자열 비교를 지정합니다. +-optioncompare:binary 이진 형식 문자열 비교를 지정합니다. + 이것이 기본값입니다. +-optioncompare:text 텍스트 형식 문자열 비교를 지정합니다. - - MISCELLANEOUS - --help 이 사용 메시지를 표시합니다. (약식: -?) --noconfig VBC.RSP 파일을 자동으로 포함하지 마세요. --nologo 컴파일러 저작권 배너를 표시하지 마세요. --quiet 조용한 출력 모드입니다. --verbose 자세한 메시지를 표시합니다. --parallel[+|-] 동시 빌드입니다. --version 컴파일러 버전 번호를 표시하고 종료합니다. + - 기타 - +-help 사용법 메시지를 표시합니다. (약식: -?) +-noconfig VBC.RSP 파일을 자동으로 포함하지 않습니다. +-nologo 컴파일러 저작권 배너를 표시하지 않습니다. +-quiet 자동 출력 모드입니다. +-verbose 자세한 메시지를 표시합니다. +-parallel[+|-] 동시 빌드입니다. +-version 컴파일러 버전 번호를 표시하고 종료합니다. - - ADVANCED - --baseaddress:<number> 라이브러리 또는 모듈의 기본 주소 - (16진수)입니다. --checksumalgorithm:<alg> PDB에 저장된 원본 파일 체크섬 - 계산 알고리즘을 지정합니다. 지원되는 값은 다음과 같습니다. - SHA1 또는 SHA256입니다(기본값). --codepage:<number> 원본 파일을 열 때 사용할 코드 페이지를 + - 고급 - +-baseaddress:<number> 라이브러리 또는 모듈의 기준 주소입니다 + (16진수). +-checksumalgorithm:<alg> PBD에 저장된 소스 파일 체크섬을 계싼하기 위한 + 알고리즘을 지정합니다. 지원되는 값은 다음과 같습니다. + SHA1 또는 SHA256(기본값)입니다. +-codepage:<number> 소스 파일을 열 때 사용할 코드 페이지를 지정합니다. --delaysign[+|-] 강력한 이름 키의 공개 부분만 사용하여 - 어셈블리를 지연 서명합니다. --publicsign[+|-] 강력한 이름 키의 공개 부분만 사용하여 - 어셈블리를 공개 서명합니다. --errorreport:<string> 내부 컴파일러 오류를 처리하는 방법을 지정합니다. - 프롬프트, 보내기, 없음 또는 큐(기본값)이어야 +-delaysign[+|-] 강력한 이름의 키의 공개 부분만 사용하여 어셈블리 서명을 + 공개적으로 진행합니다. +-publicsign[+|-] 강력한 이름의 키의 공개 부분만 사용하여 어셈블리 서명을 + 공개적으로 진행합니다. +-errorreport:<string> 내부 컴파일러 오류를 처리하는 방법을 지정합니다. + 이는 프롬프트, 보내기, 없음 또는 큐(기본값)여야 합니다. --filealign:<number> 출력 파일 섹션에 사용되는 정렬을 +-generatedfilesout:<dir> 지정된 디렉터리에 컴파일 중 생성된 파일을 + 이동합니다. +-filealign:<number> 출력 파일 섹션에 사용되는 맞춤을 지정합니다. --highentropyva[+|-] 높은 엔트로피 ASLR을 활성화합니다. --keycontainer:<string> 강력한 이름 키 컨테이너를 지정합니다. --keyfile:<file> 강력한 이름 키 파일을 지정합니다. --libpath:<path_list> 메타데이터 참조를 검색할 디렉터리 +-highentropyva[+|-] 높은 엔트로피 ASLR을 사용하도록 설정합니다. +-keycontainer:<string> 강력한 이름의 키 컨테이너를 지정합니다. +-keyfile:<file> 강력한 이름의 키 파일을 지정합니다. +-libpath:<path_list> 메타데이터 참조를 검색할 디렉터리 목록입니다. (세미콜론으로 구분됨) --main:<class> Sub Main이 포함된 클래스 또는 모듈을 - 지정합니다. System.Windows.Forms.Form에서 - 상속되는 클래스일 수도 있습니다. +-main:<class> Sub Main을 포함하는 클래스 또는 모듈을 + 지정합니다. System.Windows.Forms.Form를 상속하는 + Class도 가능합니다. (약식: -m) --moduleassemblyname:<string> 이 모듈이 속할 - 어셈블리의 이름입니다. --netcf .NET Compact Framework를 대상으로 합니다. --nostdlib 표준 라이브러리를 참조하지 마세요 - (system.dll 및 VBC.RSP 파일). +-moduleassemblyname:<string> 이 모듈이 속할 어셈블리의 + 이름입니다. +-netcf .NET Compact Framework를 지정하십시오. +-nostdlib 표준 라이브러리를 참조하지 마십시오 + (system.dll 및 VBC. RSP 파일). -pathmap:<K1>=<V1>,<K2>=<V2>,... - 컴파일러에서 출력하는 원본 경로 이름에 대한 매핑을 - 지정합니다. --platform:<string> 이 코드를 실행할 수 있는 플랫폼을 제한합니다. - x86, x64, Itanium, arm, arm64여야 합니다. - AnyCPU32BitPreferred 또는 anycpu(기본값). --preferreduilang 기본 출력 언어 이름을 지정합니다. --nosdkpath 표준 라이브러리 어셈블리에 대한 기본 SDK 경로 검색을 비활성화합니다. --sdkpath:<path> .NET Framework SDK 디렉터리의 위치 + 컴파일러를 이용하여 원본 경로 이름 출력의 매핑을 + 구체화합니다. +-platform:<string> 이 코드를 실행할 수 있는 플랫폼을 제한합니다. + x86, x64, Itanium, arm, arm64 + AnyCPU32BitPreferred 또는 anycpu(기본값)이어야 합니다. +-preferreduilang 기본 출력 언어 이름을 지정합니다. +-nosdkpath 표준 라이브러리 어셈블리의 기본 SDK 경로 검색을 사용하지 않도록 설정합니다. +-sdkpath:<path> .NET Framework SDK 디렉터리 위치 (mscorlib.dll). --subsystemversion:<version> 출력 PE의 하위 시스템 버전을 지정합니다. - version:<number>[.<number>] --utf8output[+|-] UTF-8 문자 인코딩으로 컴파일러 출력을 +-subsystemversion:<version> 출력 PE의 하위 시스템 버전을 지정하십시오. + 버전:<number>[.<숫자>] +-utf8output[+|-] UTF8 문자 인코딩으로 컴파일러 출력을 내보냅니다. -@<file> 텍스트 파일에서 명령줄 설정을 삽입합니다 --vbruntime[+|-|*] 기본 Visual Basic 런타임을 사용하거나 사용하지 않고 - 컴파일합니다. --vbruntime:<file> <file>에서 대체 Visual Basic 런타임으로 +@<file> 텍스트 파일에서 명령줄 설정을 삽입합니다. +-vbruntime[+|-|*] 기본 Visual Basic 런타임을 사용하거나 사용하지 않고 + 컴파일합니다. +-vbruntime:<file> <file>에서 대체 Visual Basic 런타임을 사용하여 컴파일합니다. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index 787927d953087..ebb8cc4ef576d 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -269,169 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Opcje kompilatora Visual Basic + Opcje kompilatora Visual Basic - - OUTPUT FILE - + - PLIK WYJŚCIOWY - -out:<file> Określa nazwę pliku wyjściowego. --target:exe Tworzenie aplikacji konsoli (ustawienie domyślne). - (Skrócona forma: -t) --target:winexe Tworzenie aplikacji systemu Windows. --target:library Tworzenie zestawu bibliotek. --target:module Tworzenie modułu, który można dodać do - zestawu. --target:appcontainerexe Tworzenie aplikacji systemu Windows, która działa w środowisku +-target:exe Utwórz aplikację konsoli (domyślne). + (Krótki formularz: -t) +-target:winexe Utwórz aplikację systemu Windows. +-target:library Utwórz zestaw biblioteki. +-target:module Utwórz moduł, który można dodać do + zestaw. +-target:appcontainerexe Utwórz aplikację systemu Windows, która działa w AppContainer. --target:winmdobj Tworzenie pliku pośredniego metadanych systemu Windows +-target:winmdobj Utwórz pośredni plik metadanych systemu Windows -doc[+|-] Generuje plik dokumentacji XML. --doc:<file> Generuje plik dokumentacji XML do pliku <file>. --refout:<file> Dane wyjściowe zestawu odwołania do wygenerowania +-doc:<file> Generuje plik dokumentacji XML w pliku <file>. +-refout:<file> Odwołanie do danych wyjściowych zestawu do wygenerowania - - INPUT FILES - + - PLIKI WEJŚCIOWE - -addmodule:<file_list> Metadane odwołania z określonych modułów --link:<file_list> Osadzanie metadanych z określonego zestawu - międzyoperacyjnego. (Skrócona forma: -l) --recurse:<wildcard> Uwzględnianie wszystkich plików w bieżącym katalogu - i podkatalogach zgodnie ze - specyfikacjami symboli wieloznacznych. --reference:<file_list> Metadane odwołania z określonego - zestawu. (Skrócona forma: -r) --analyzer:<file_list> Uruchamianie analizatorów z tego zestawu - (Skrócona forma: -a) --additionalfile:<file list> Dodatkowe pliki, które nie wpływają bezpośrednio na generowanie - kodu, ale mogą być używane przez analizatory na potrzeby generowania - błędów lub ostrzeżeń. +-link:<file_list> Osadzone metadane z określonej międzyoperacyjności + zestaw. (Krótki formularz: -l) +-recurse:<wildcard> Uwzględnij wszystkie pliki w bieżącym katalogu + i podkatalogów zgodnie z + specyfikacje symboli wieloznacznych. +-reference:<file_list> Metadane odwołania z określonego elementu + zestaw. (Krótki formularz: -r) +-analyzer:<file_list> Uruchom analizatory z tego zestawu + (Krótki formularz: -a) +-additionalfile:<file list> Dodatkowe pliki, które nie mają bezpośredniego wpływu na kod + generowania, ale może być używana przez analizatory do produkcji + brak błędów i ostrzeżeń. - - RESOURCES - + - ZASOBY - -linkresource:<resinfo> Łączy określony plik jako zewnętrzny zasób zestawu. - resinfo:<file>[,<name>[,public|private]] - (Skrócona forma: -linkres) --nowin32manifest Nie należy osadzać domyślnego manifestu - w sekcji manifestu pliku wyjściowego PE. --resource:<resinfo> Dodaje plik w postaci osadzonej - assembly resource. - resinfo:<file>[,<name>[,public|private]] - (Skrócona forma: -res) + resinfo:<file>[,<name>[,publiczny|prywatny]] + (Krótki formularz: -linkres) +-nowin32manifest Manifest domyślny nie powinien być osadzony + w sekcji manifestu wyjściowego środowiska PE. +-resource:<resinfo> Dodaje określony plik jako osadzony + zasób zestawu. + resinfo:<file>[,<nazwa>[,publiczny|prywatny]] + (Krótki formularz: -res) -win32icon:<file> Określa plik ikony Win32 (.ico) dla - zasobów domyślnych Win32. --win32manifest:<file> Podany plik jest osadzony w sekcji - manifestu pliku wyjściowego PE. --win32resource:<file> Określa plik zasobu Win32 (.res). + domyślne zasoby Win32. +-win32manifest:<file> Podany plik jest osadzony w manifeście + sekcji wyjściowego środowiska PE. +-win32resource:<file> Określa plik zasobów Win32 (res) - - CODE GENERATION - --optimize[+|-] Włączanie optymalizacji. --removeintchecks[+|-] Usuwanie kontroli liczb całkowitych. Ustawienie domyślne wyłączone. --debug[+|-] Wysyłanie informacji o debugowaniu. --debug:full Wysyłanie pełnych informacji o debugowaniu (domyślnie). --debug:pdbonly Wysyłanie pełnych informacji o debugowaniu. --debug:portable Wysyłanie informacji o międzyplatformowym debugowaniu. --debug:embedded Wysyłanie informacji o międzyplatformowym debugowaniu do - docelowego pliku .dll lub .exe. --deterministic Tworzenie deterministycznego zestawu - (w tym identyfikatora GUID i znacznika czasu wersji modułu) --refonly Tworzenie zestawu odwołania w miejsce wyjścia głównego --instrument:TestCoverage Tworzenie zestawu zinstrumentowanego na zbieranie -  informacji o pokryciu --sourcelink:<file> Informacje o linku do źródła do osadzenia w pliku PDB. + - GENEROWANIE KODU - +-optimize[+|-] Włącz optymalizacje. +-removeintchecks[+|-] Usuń testy liczb całkowitych. Wartość domyślna jest wyłączona. +-debug[+|-] Emituj informacje o debugowaniu. +-debug:full Emituj pełne informacje o debugowaniu (domyślnie). +-debug:pdbonly Emituj pełne informacje debugowania. +-debug:portable Emituj informacje debugowania międzyplatformowego. +-debug:embedded Emituj informacje debugowania międzyplatformowego do + docelowy plik dll lub exe. +-deterministic Produkuj zestawy deterministyczne + (w tym identyfikator GUID wersji modułu i sygnatura czasowa) +-refonly Utwórz zestaw referencyjny zamiast głównego wyjścia +-instrument:TestCoverage Utwórz zestaw instrumentowany do zbierania + informacje o pokryciach +-sourcelink:<file> Informacje o linku źródłowym, aby osadzić w bazie danych PDB. - - ERRORS AND WARNINGS - --nowarn Wyłączanie wszystkich ostrzeżeń. --nowarn:<number_list> Wyłączanie listy poszczególnych ostrzeżeń. --warnaserror[+|-] Traktowanie wszystkich ostrzeżeń jako błędów. --warnaserror[+|-]:<number_list> Traktowanie listy ostrzeżeń jako błędów. --ruleset:<file> Określanie pliku zestawu reguł, który wyłącza określone - dane diagnostyczne. + - BŁĘDY I OSTRZEŻENIA - +-nowarn Wyłącz wszystkie ostrzeżenia. +-nowarn:<number_list> Wyłącz listę poszczególnych ostrzeżeń. +-warnaserror[+|-] Traktuj wszystkie ostrzeżenia jako błędy. +-warnaserror[+|-]:<number_list> Traktuj listę ostrzeżeń jako błędy. +-ruleset:<file> Określ plik zestawu reguł, który wyłącza określone + diagnostyka. -errorlog:<file>[,version=<sarif_version>] - Określanie pliku do rejestrowania wszystkich danych diagnostycznych - kompilatora i analizatora w formacie SARIF. - sarif_version:{1|2|2.1} Wartości domyślne to 1. 2 i 2.1, które - oznaczają SARIF w wersji 2.1.0. --reportanalyzer Raportowanie dodatkowych informacji analizatora, takich jak + Określ plik do rejestrowania całego kompilatora i analizatora + diagnostyki w formacie SARIF. + sarif_version:{1|2|2.1} Wartość domyślna to 1. 2 i 2.1 + średnia wersja SARIF 2.1.0. +-reportanalyzer Raport dodatkowe informacje analizatora, takie jak czas wykonania. --skipanalyzers[+|-] Pomijanie wykonania analizatorów diagnostycznych. +-skipanalyzers[+|-] Pomiń wykonywanie analizatorów diagnostycznych. - - LANGUAGE - + - JĘZYK - -define:<symbol_list> Deklarowanie globalnej kompilacji warunkowej - symbol(s). symbol_list:name=value,... - (Skrócona forma: -d) + symbol (-e). symbol_list:nazwa=wartość,... + (Krótki formularz: -d) -imports:<import_list> Deklarowanie globalnych importów dla przestrzeni nazw w - przywoływanych plikach metadanych. - import_list:namespace,... --langversion:? Wyświetlanie dozwolonych wartości dla wersji języka --langversion:<string> Określanie wersji języka, takiej jak - „default” (najnowsza wersja główna) lub - „latest” (najnowsze wersja, w tym wersje główne) - albo określone wersje, np. „14” lub „15.3” --optionexplicit[+|-] Wymaganie jawnej deklaracji zmiennych. --optioninfer[+|-] Zezwalanie na wnioskowanie o typie zmiennych. --rootnamespace:<string> Określa przestrzeń nazwa katalogu głównego dla wszystkich deklaracji - typu. --optionstrict[+|-] Wymuszanie jednoznacznej semantyki języka. --optionstrict:custom Ostrzeganie, gdy jednoznaczna semantyka języka nie jest - przestrzegana. --optioncompare:binary Określa porównania ciągów ze stylem binarnym. + przywoływanych plików metadanych. + import_list:przestrzeń nazw,... +-langversion:? Wyświetl dozwolone wartości dla wersji językowej +-langversion:<string> Określ wersję języka, na przykład + `default` (najnowsza wersja główna) lub + `latest` (najnowsza wersja, w tym wersje pomocnicze), + lub określone wersje, takie jak `14` lub `15.3` +-optionexplicit[+|-] Wymagaj jawnej deklaracji zmiennych. +-optioninfer[+|-] Zezwalaj na wnioskowanie typów zmiennych. +-rootnamespace:<string> Określa główną przestrzeń nazw dla wszystkich typów + deklaracje. +-optionstrict[+|-] Wymuszaj ścisłą semantykę języka. +-optionstrict:custom Ostrzegaj, gdy ścisła semantyka języka nie jest + przestrzegane. +-optioncompare:binary Określa porównania ciągów w stylu binarnym. Jest to ustawienie domyślne. --optioncompare:text Określa porównania ciągów ze stylem tekstowym. +-optioncompare:text Określa porównania ciągów w stylu tekstu. - - MISCELLANEOUS - --help Wyświetlanie komunikatu o tym użyciu. (Skrócona forma: -?) --noconfig Nie uwzględniaj automatycznie pliku VBC.RSP. --nologo Nie wyświetlaj transparentu praw autorskich kompilatora. --quiet Cichy tryb wyjścia. --verbose Wyświetlanie pełnych komunikatów. --parallel[+|-] Kompilacja współbieżna. --version Wyświetlanie numeru wersji kompilatora i zamykanie. + - RÓŻNE - +-help Wyświetla ten komunikat dotyczący użycia. (Krótki formularz: -?) +-noconfig Nie dołącza automatycznie pliku VBC.RSP. +-nologo Nie wyświetlaj transparentu kompilatora z informacjami o prawach autorskich. +-quiet Cichy tryb wyjściowy. +-verbose Wyświetl szczegółowe komunikaty. +-parallel[+|-] Współbieżna kompilacja. +-version Wyświetl numer wersji kompilatora i zakończ. - - ADVANCED - --baseaddress:<number> Adres bazowy biblioteki lub modułu + - ZAAWANSOWANA - +-baseaddress:<number> Adres podstawowy biblioteki lub modułu (hex). --checksumalgorithm:<alg> Określanie algorytmu dla pliku źródłowego obliczania - sumy kontrolnej przechowywanej w pliku PDB. Obsługiwane wartości to: - SHA1 lub SHA256 (domyślnie). +-checksumalgorithm:<alg> Określ algorytm obliczania pliku źródłowego + suma kontrolna przechowywana w bazie danych PDB. Obsługiwane wartości to: + SHA1 lub SHA256 (wartość domyślna). -codepage:<number> Określa stronę kodową do użycia podczas otwierania - plików źródłowych. --delaysign[+|-] Podpisanie zestawu z opóźnieniem przy użyciu wyłącznie publicznej - części silnego klucza nazwy. --publicsign[+|-] Podpisanie publiczne zestawu przy użyciu wyłącznie publicznej - części silnego klucza nazwy. --errorreport:<string> Określa sposób obsługi błędów wewnętrznych - kompilatora; musi być prompt, send, none lub queue - (domyślnie). --filealign:<number> Określanie wyrównania dla sekcji - pliku wyjściowego. --highentropyva[+|-] Włączanie losowego generowania układu przestrzeni adresowej o wysokiej entropii. --keycontainer:<string> Określa konterner silnych kluczy nazw. --keyfile:<file> Określa plik silnego klucza nazwy. --libpath:<path_list> Lista katalogów do wyszukania odwołań - metadanych. (Rozdzielone średnikami). + pliki źródłowe. +-delaysign[+|-] Opóźnienie podpisywania zestawu przy użyciu tylko publicznego + część klucza silnej nazwy. +-publicsign[+|-] Podpisz zestaw jako publiczny + część klucza silnej nazwy. +-errorreport:<string> Określa sposób obsługi wewnętrznego kompilatora + błędy; musi być monitem, wysyłaniem, brakiem lub kolejką + (domyślne). +-generatedfilesout:<dir> Umieść pliki wygenerowane podczas kompilacji w + określony katalog. +-filealign:<number> Określ wyrównanie używane dla pliku wyjściowego + sekcje. +-highentropyva[+|-] Włącz funkcję ASLR o wysokiej entropii. +-keycontainer:<string> Określa kontener klucza o silnej nazwie. +-keyfile:<file> Określa plik klucza silnej nazwy. +-libpath:<path_list> Lista katalogów do wyszukania metadanych + odwołania. (Rozdzielone średnikami). -main:<class> Określa klasę lub moduł zawierający - instrukcję Sub Main. Może to być również klasa, która - dziedziczy po elemencie System.Windows.Forms.Form. - (Skrócona forma: -m) --moduleassemblyname:<string> Nazwa zestawu, do którego - należy ten moduł. --netcf Docelowe środowisko .NET Compact Framework. --nostdlib Nie odwołuj się do bibliotek standardowych - (pliki system.dll i VBC.RSP). + Sub Main. Może to być również klasa, która + dziedziczy z elementu System.Windows.Forms.Form. + (Krótki formularz: -m) +-moduleassemblyname:<string> Nazwa zestawu, który ten moduł będzie + być częścią. +-netcf Wskaż platformę .NET Compact Framework jako element docelowy. +-nostdlib Nie należy odwoływać się do bibliotek standardowych + (system.dll i VBC. pliku RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... - Określanie mapowania dla wyjścia nazw ścieżek źródłowych przez - kompilator. --platform:<string> Ograniczanie, na których platformach może działać ten kod; + Określ mapowanie dla nazw ścieżek źródłowych według + kompilatora. +-platform:<string> Ogranicz platformy, na których można uruchomić ten kod; musi być x86, x64, Itanium, arm, arm64 - AnyCPU32BitPreferred lub anycpu (domyślnie). --preferreduilang Określanie nazwy preferowanego języka wyjściowego. --nosdkpath Wyłączania wyszukiwania ścieżki zestawu SDK dla zestawów bibliotek standardowych. --sdkpath:<path> Lokalizacja katalogu zestawu SDK .NET Framework + AnyCPU32BitPreferred lub anycpu (wartość domyślna). +-preferreduilang Określ preferowaną nazwę języka wyjściowego. +-nosdkpath Wyłącz wyszukiwanie domyślnej ścieżki zestawu SDK dla zestawów biblioteki standardowe. +-sdkpath:<path> Lokalizacja katalogu zestawu .NET Framework SDK (mscorlib.dll) (mscorlib.dll). --subsystemversion:<version> Określanie wersji podsystemu pliku wyjściowego PE. +-subsystemversion:<version> Określ wersję podsystemu wyjściowego środowiska PE. version:<number>[.<number>] --utf8output[+|-] Wysyłanie danych wyjściowych kompilatora w systemie kodowania znaków - UTF-8. -@<file> Wstawianie ustawień w wierszu polecenia z pliku tekstowego --vbruntime[+|-|*] Kompilowanie z/bez domyślnego aparatu plików wykonywalnych języka wspólnego - Visual Basic. --vbruntime:<file> Kompilowanie z alternatywnym aparatem plików wykonywalnych języka wspólnego - Visual Basic w pliku <file>. +-utf8output[+|-] Emituj dane wyjściowe kompilatora w znaku UTF-8 + kodowanie. +@<file> Wstaw ustawienia wiersza polecenia z pliku tekstowego +-vbruntime[+|-|*] Kompiluj z/bez użycia domyślnej wersji wykonywalnej programu Visual Basic. + środowisko uruchomieniowe. +-vbruntime:<file> Kompiluj z użyciem zastępczej wersji wykonywalnej programu Visual Basic z pliku + środowisko uruchomieniowe w <file>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index e8b45128f680e..e0b4c6b51bdaa 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -269,169 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Opções do Compilador Visual Basic + Opções do compilador do Visual Basic - ARQUIVO DE SAÍDA - --out:<file> Especifica o nome do arquivo de saída. --target:exe Cria um aplicativo do console (padrão). - (Forma abreviada: -t) --target:winexe Cria um aplicativo do Windows. --target:library Cria um assembly de biblioteca. --target:module Cria um módulo que pode ser adicionado a um assembly - aplicativo. --target:appcontainerexe Cria um aplicativo do Windows que é executado +-out:<file> Especifica o nome do arquivo de saída. +-target:exe Criar um aplicativo de console (padrão). + (Forma curta: -t) +-target:winexe Criar um aplicativo do Windows. +-target:library Criar um assembly de biblioteca. +-target:module Cria um módulo que pode ser adicionado a um + assembly. +-target:appcontainerexe Crie um aplicativo do Windows que seja executado em AppContainer. --target:winmdobj Cria um arquivo intermediário de Metadados do Windows --doc[+|-] Gera um arquivo de documentação XML. --doc:<file> Gera o arquivo de documentação XML para <file>. --refout:<file> Saída de assembly de referência para gerar +-target:winmdobj Crie um arquivo intermediário de Metadados do Windows +-doc[+|-] Gera arquivo de documentação XML. +-doc:<file> Gera arquivo de documentação XML para <file>. +-refout:<file> Saída de montagem de referência para gerar - - ARQUIVOS DE ENTRADA- + - ARQUIVOS DE ENTRADA - -addmodule:<file_list> Metadados de referência dos módulos especificados --link:<file_list> Inserir metadados do assembly de interoperabilidade - especificado. (Forma abreviada: -l) --recurse:<wildcard> Inclua todos os arquivos no diretório atual - e subdiretórios de acordo com as - especificações de curinga. --reference:<file_list> Metadados de referência do assembly - especificado. (Forma abreviada: -r) --analyzer:<file_list> Executa os analisadores deste assembly +-link:<file_list> Incorporar metadados da interoperabilidade especificada + assembly. (Forma abreviada: -l) +-recurse:<wildcard> Incluir todos os arquivos no diretório atual + e subdiretórios de acordo com o + especificações curinga. +-reference:<file_list> Metadados de referência do especificado + assembly. (Forma abreviada: -r) +-analyzer:<file_list> Execute os analisadores desta montagem (Forma abreviada: -a) --additionalfile:<file list> Arquivos adicionais que não afetam diretamente o a geração - do código mas podem ser usados pelos analisadores para a produção de +-additionalfile:<file list> Arquivos adicionais que não afetam diretamente o código + geração, mas pode ser usado por analisadores para produzir erros ou avisos. - RECURSOS - --linkresource:<resinfo> Conecta o arquivo especificado como um recurso - assembly externo. +-linkresource:<resinfo> Vincula o arquivo especificado como um arquivo externo + recurso de montagem. resinfo:<file>[,<name>[,public|private]] (Forma abreviada: -linkres) -nowin32manifest O manifesto padrão não deve ser incorporado na seção de manifesto do PE de saída. --resource:<resinfo> Adiciona o arquivo especificado como um recurso assembly - específico. +-resource:<resinfo> Adiciona o arquivo especificado como um incorporado + recurso de montagem. resinfo:<file>[,<name>[,public|private]] (Forma abreviada: -res) --win32icon:<file> Especifica um arquivo de ícone do Win32 (.ico) para os +-win32icon:<file> Especifica um arquivo de ícone Win32 (.ico) para o recursos padrão do Win32. --win32manifest:<file> O arquivo fornecido é incorporado na seção de saída PE - no manifesto. --win32resource:<file> Especifica um arquivo de recurso (.res) do Win32. +-win32manifest:<file> O arquivo fornecido está incorporado no manifesto + seção da saída PE. +-win32resource:<file> Especifica um arquivo de recurso Win32 (.res). - GERAÇÃO DE CÓDIGO - -optimize[+|-] Habilitar otimizações. --removeintchecks[+|-] Remover verificações inteiras. Padrão desabilitado. +-removeintchecks[+|-] Remover verificações de números inteiros. Padrão desativado. -debug[+|-] Emite informações de depuração. --debug:full Emite informações de depuração completas (default). --debug:pdbonly Emite informações de depuração completas. --debug:portable Emite informações de depuração de plataforma cruzada. --debug:embedded Emite informações de depuração de plataforma cruzada no - .dll or .exe. do destino --determinístico Produz o assembly determinístico - (incluindo o GUID de versão de módulo e carimbo de data/hora) --refonly Produz o assembly de referência no lugar da saída principal --instrument:TestCoverage Produz um assembly instrumentado para coletar +-debug:full Emite informações completas de depuração (padrão). +-debug:pdbonly Emite informações completas de depuração. +-debug:portable Emite informações de depuração entre plataformas. +-debug:embedded Emita informações de depuração de plataforma cruzada para + o .dll ou .exe de destino. +-deterministic Produzir uma montagem determinística + (incluindo GUID da versão do módulo e carimbo de data/hora) +-refonly Produzir uma montagem de referência no lugar da saída principal +-instrument:TestCoverage Produzir uma montagem instrumentada para coletar informações de cobertura --sourcelink:<file> Informações do link de origem para incorporar ao PDB. +-sourcelink:<file> Informações do link de origem para incorporar no PDB. - ERROS E AVISOS - --nowarn Desabilita todos os avisos. --nowarn:<number_list> Desabilita uma lista de avisos individuais. --warnaserror[+|-] Trata todos os avisos como erros. --warnaserror[+|-]:<number_list> Trata uma lista de avisos como erros. --ruleset:<file> Especifica um arquivo de conjunto de regras que desabilita diagnósticos - específicos. --errorlog:<file>[,version=<sarif_version>] - Especifica um arquivo para registrar todos os diagnósticos do - complidaor e analisador no formato SARIF. - sarif_version:{1|2|2.1} Padrão é 1.2 and 2.1 - ambos significam a versão SARIF 2.1.0. --reportanalyzer Reporta informações adicionais do analisador, como +-nowarn Desabilitar todos os avisos. +-nowarn:<number_list> Desabilitar uma lista de avisos individuais. +-warnaserror[+|-] Trate todos os avisos como erros. +-warnaserror[+|-]:<number_list> Tratar uma lista de avisos como erros. +-ruleset:<file> Especifique um arquivo de conjunto de regras que desabilita determinados + diagnósticos. +-errorlog:<file>[,versão=<sarif_version>] + Especifique um arquivo para registrar todo o compilador e analisador + diagnóstico em formato SARIF. + sarif_version:{1|2|2.1} Padrão é 1. 2 e 2.1 + ambos significam versão SARIF 2.1.0. +-reportanalyzer Relatar informações adicionais do analisador, como tempo de execução. --skipanalyzers[+|-] Salta a execução dos analisadores de diagnóstico. +-skipanalyzers[+|-] Ignorar a execução de analisadores de diagnóstico. - IDIOMA - --define:<symbol_list> Declara compilação condicional global - symbol(s). symbol_list:name=value,... +-define:<symbol_list> Declarar compilação condicional global + símbolo(s). symbol_list:name=value,... (Forma abreviada: -d) --imports:<import_list> Declara importações globais para namespaces em - metadados referenciados. +-imports:<import_list> Declarar importações globais para namespaces em + arquivos de metadados referenciados. import_list:namespace,... --langversion:? Exibe os valores permitidos para --langversion:<string> Especifica a versão de idioma como - `padrão` (versão principal mais recente) ou - `recente` (versão mais recente, incluindo versões secundárias), +-langversion:? Exibir os valores permitidos para a versão do idioma +-langversion:<string> Especifique a versão do idioma, como + `default` (última versão principal), ou + `latest` (versão mais recente, incluindo versões secundárias), ou versões específicas como `14` or `15.3` --optionexplicit[+|-] Exige declaração explícita de variáveis. --optioninfer[+|-] Permite inferência de tipo de variáveis. --rootnamespace:<string> Especifica a raiz do Namespace para todos os tipos de +-optionexplicit[+|-] Requer declaração explícita de variáveis. +-optioninfer[+|-] Permitir inferência de tipo de variáveis. +-rootnamespace:<string> Especifica o Namespace raiz para todos os tipos declarações. --optionstrict[+|-] Enforça semânticas de idioma estritas. --optionstrict:custom Avisa quando as semânticas de idioma restritas não são - respeitadas. --optioncompare:binary Especifica as comparações das cadeias de estilo binárias. +-optionstrict[+|-] Aplicar semântica de linguagem estrita. +-optionstrict:custom Avisar quando a semântica estrita da linguagem não for + respeitado. +-optioncompare:binary Especifica comparações de cadeia de caracteres de estilo binário. Este é o padrão. --optioncompare:text Especifica as comparações da cadeia texto-estilo. +-optioncompare:text Especifica comparações de cadeia de estilo de texto. - DIVERSOS - --help Exibe essa mensagem de uso. (Forma abreviada: -?) --noconfig Não inclui automaticamente o arquivo VBC.RSP. --nologo Não exibe o banner de direitos autorais do compilador. +-help Exibir esta mensagem de uso. (Forma abreviada: -?) +-noconfig Não inclua automaticamente o arquivo VBC.RSP. +-nologo Não exibir banner de direitos autorais do compilador. -quiet Modo de saída silencioso. --verbose Exibe mensagens verbosas. --parallel[+|-] Compilação simultânea. --version Exibe a saída e número de versão do compilador. +-verbose Exibir mensagens detalhadas. +-parallel[+|-] compilação simultânea. +-version Exiba o número da versão do compilador e saia. - AVANÇADO - --baseaddress:<number> O endereço básico para uma biblioteca ou módulo +-baseaddress:<number> O endereço base para uma biblioteca ou módulo (hex). --checksumalgorithm:<alg> Especifica o algoritmo para calcular o arquivo de origem - soma de verificação armazenada no PDB. Os valores com suporte são: - SHA1 or SHA256 (padrão). +-checksumalgorithm:<alg> Especifique o algoritmo para calcular o arquivo de origem + csoma de verificação armazenada no PDB. Os valores suportados são: + SHA1 ou SHA256 (padrão). -codepage:<number> Especifica a página de código a ser usada ao abrir arquivos de origem. --delaysign[+|-] Assina o assembly com atraso usando apenas a parte pública - da chave de nome forte. --publicsign[+|-] Assina o assembly público usando apenas a parte pública - da chave de nome forte. --errorreport:<string> Especifica como tratar erros internos do compilador - erros; devem ser prompt, send, none, or queue +-delaysign[+|-] Atrasar a assinatura do assembly usando apenas o público + parte da chave de nome forte. +-publicsign[+|-] Assinar publicamente o assembly usando apenas o público + parte da chave de nome forte. +-errorreport:<string> Especifica como lidar com o compilador interno + erros; deve ser prompt, enviar, nenhum ou fila (padrão). --filealign:<number> Especifica o alinhamento usado para seções de marcador - de saída. --highentropyva[+|-] Habilita ASLR de alta entropia. --keycontainer:<string> Especifica um contêiner de chave de nome fort.. +-generatedfilesout:<dir> Coloque os arquivos gerados durante a compilação no + diretório especificado. +-filealign:<number> Especifique o alinhamento usado para o arquivo de saída + Seções. +-highentropyva[+|-] Habilite o ASLR de alta entropia. +-keycontainer:<string> Especifica um contêiner de chave de nome forte. -keyfile:<file> Especifica um arquivo de chave de nome forte. --libpath:<path_list> Lista de diretórios a serem pesquisados por referências - de metadados. (Delimitado por ponto e vírgula.) --main:<class> Especifica a classe ou módulo que contém - Sub main. Também pode ser uma Classe que - herda do System.Windows.Forms.Form. +-libpath:<path_list> Lista de diretórios para pesquisar metadados + referências. (Delimitado por ponto e vírgula.) +-main:<class> Especifica a Classe ou Módulo que contém + Sub Principal. Também pode ser uma Classe que + herda de System.Windows.Forms.Form. (Forma abreviada: -m) --moduleassemblyname:<string> Nome do assembly do qual este módulo - será parte. --netcf Especifica o .NET Compact Framework. --nostdlib Não referencia as bibliotecas padrão de referência - (system.dll and VBC.RSP file). +-moduleassemblyname:<string> Nome do assembly que este módulo irá + fazer parte de. +-netcf Direcione o .NET Compact Framework. +-nostdlib Não faça referência a bibliotecas padrão + (arquivo system.dll e VBC.RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... - Especifica um mapeamento para saída de nomes de caminho de origem pelo - compilador. --platform:<string> Limita em quais plataformas esse código pode ser executado; - deve ser x86, x64, Itanium, arm, arm64 + Especifique um mapeamento para saída de nomes de caminho de origem por + o compilador. +-platform:<string> Limite em quais plataformas esse código pode ser executado; + must be x86, x64, Itanium, arm, arm64 AnyCPU32BitPreferred ou anycpu (padrão). --preferreduilang Especifica o nome do idioma de saída preferencial. --nosdkpath Desabilita a pesquisa no caminho do SDK padrão para assemblies de biblioteca padrão. --sdkpath:<path> Local do diretório do SDK .NET Framework - (mscorlib.dll). --subsystemversion:<version> Especifica a versão do subsistema do PE de saída. +-preferreduilang Especifique o nome do idioma de saída preferido. +-nosdkpath Desabilitar a pesquisa do caminho padrão do SDK para conjuntos de bibliotecas padrão. +-sdkpath:<path> Local do diretório SDK do .NET Framework + (mscorlib.dll). +-subsystemversion:<version> Especifique a versão do subsistema do PE de saída. versão:<number>[.<number>] --utf8output[+|-] Emite a saída do compilador na codificação de caracteres UTF-8 - . +-utf8output[+|-] Emite a saída do compilador no caractere UTF-8 + codificação. @<file> Inserir configurações de linha de comando de um arquivo de texto --vbruntime[+|-|*] Compila com/sem o runtime padrão do Visual Basic - . --vbruntime:<file> Compile com o runtime de Visual Basic - alternativo em <file>. +-vbruntime[+|-|*] Compilar com/sem o Visual Basic padrão + tempo de execução. +-vbruntime:<file> Compilar com o Visual Basic alternativo + tempo de execução em <file>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf index 5c9de787b29ad..0b0ff244cdc2b 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ru.xlf @@ -269,168 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Параметры компилятора Visual Basic + Параметры компилятора Visual Basic - ВЫХОДНОЙ ФАЙЛ - --out:<файл> Указывает имя выходного файла. +-out: <файл> Задает имя выходного файла. -target:exe Создать консольное приложение (по умолчанию). (Краткая форма: -t) --target:winexe Создать приложение Windows. --target:library Создать сборку библиотеки. --target:module Создать модуль для добавления - в сборку. --target:appcontainerexe Создать приложение Windows, которое выполняется в +-target:winexe Создать приложение для Windows. +-target:library Создать библиотечную сборку. +-target:module Создать модуль, который может быть добавлен в + сборку. +-target:appcontainerexe Создать приложение для Windows, выполняемое в AppContainer. -target:winmdobj Создать промежуточный файл метаданных Windows --doc[+|-] Создать файл документации XML. --doc:<файл> Создать файл документации XML в <файле>. --refout:<файл> Вывод базовой сборки для создания +-doc[+|-] Создает XML-файл документации. +-doc:<файл> Создает XML-файл документации <file>. +-refout:<файл> Указать выходные данные сборки для создания - ВХОДНЫЕ ФАЙЛЫ - --addmodule:<список_файлов> Создать ссылки на метаданные из указанных модулей --link:<список_файлов> Внедрить метаданные из указанной сборки +-addmodule:<список_файлов> Указать метаданные из заданных модулей +-link:<список_файлов> Внедрять метаданные из указанной сборки взаимодействия. (Краткая форма: -l) --recurse:<шаблон> Включить все файлы в текущем каталоге - и в подкаталогах в соответствии - с заданным шаблоном. --reference:<список_файлов> Создать ссылки на метаданные из указанной +-recurse:<подстановочный знак> Включить все файлы в текущем каталоге + и подкаталогах в соответствии со + спецификациями подстановочных знаков. +-reference:<список_файлов> Указать метаданные из указанной сборки. (Краткая форма: -r) --analyzer:<список_файлов> Запустить анализаторы из этой сборки - (краткая форма: -a) --additionalfile:<список файлов> Дополнительные файлы, которые не повлияют на создание - кода, но могут использоваться анализаторами для вывода - ошибок или предупреждений. +-analyzer:<список_файлов> Запустить анализаторов из этой сборки + (Краткая форма: : -a) +-additionalfile:<список_файлов> Дополнительные файлы, которые не влияют непосредственно на создание кода +, + но которые могут использоваться анализаторами для создания + ошибок и предупреждений. - РЕСУРСЫ - --linkresource:<resinfo> Ссылка на указанный файл в качестве внешнего - ресурса сборки. - resinfo:<файл>[,<имя>[,public|private]] +-linkresource:<resinfo> Связывает указанный файл как внешний + ресурс сборки. + resinfo: <файл>[,<имя>[,открытый|закрытый]] (Краткая форма: -linkres) --nowin32manifest Не внедрять манифест по умолчанию - в раздел манифеста выходной PE. --resource:<resinfo> Добавить указанный файл в качестве внедренного - ресурса сборки. - resinfo:<файл>[,<имя>[,public|private]] +-nowin32manifest Манифест по умолчанию не должен быть внедрен + в раздел манифеста выходного PE. +-resource:<resinfo> Добавляет указанный файл как внедренный + ресурс сборки. + resinfo: <файл>[,<имя>[,открытый|закрытый]] (Краткая форма: -res) --win32icon:<файл> Указывает файл значка Win32 (.ICO) для +-win32icon:<файл> Задает файл значка win32icon (.ico) для ресурсов Win32 по умолчанию. -win32manifest:<файл> Предоставленный файл внедрен в раздел - манифеста в выходной PE. --win32resource:<файл> Указывает файл ресурса Win32 (.RES). + манифеста выходного PE. +-win32resource:<файл> Задает файл ресурсов Win32 (.res). - СОЗДАНИЕ КОДА - -optimize[+|-] Включить оптимизацию. --removeintchecks[+|-] Удалить целочисленные проверки. По умолчанию: выключено. +-removeintchecks[+|-] Удалить целочисленные проверки. По умолчанию отключено. -debug[+|-] Выдавать отладочные сведения. -debug:full Выдавать полные отладочные сведения (по умолчанию). -debug:pdbonly Выдавать полные отладочные сведения. --debug:portable Выдавать кроссплатформенные отладочные сведения. --debug:embedded Выдавать кроссплатформенные отладочные сведения в целевой - файл .DLL или .EXE. +-debug:portable Выдавать кроссплатформенную информацию отладки. +-debug:embedded Выдавать кроссплатформенную информацию отладки в + целевой .dll или .exe. -deterministic Создать детерминированную сборку (включая GUID версии модуля и метку времени) --refonly Создать базовую сборку вместо основного вывода +-refonly Создать базовую сборку в качестве основного вывода -instrument:TestCoverage Создать сборку, оснащенную для сбора сведений о покрытии --sourcelink:<файл> Сведения об исходной ссылке для внедрения в PDB. +-sourcelink:<файл> Сведения об исходной ссылке для встраивания в PDB. - ОШИБКИ И ПРЕДУПРЕЖДЕНИЯ - -nowarn Отключить все предупреждения. --nowarn:<список_чисел> Отключить отдельные предупреждения, перечисленные в списке. +-nowarn:<список_чисел> Отключить список индивидуальных предупреждений. -warnaserror[+|-] Обрабатывать все предупреждения как ошибки. --warnaserror[+|-]:<список_чисел> Обрабатывать предупреждения в списке как ошибки. --ruleset:<файл> Указать файл набора правил, отключающего определенную +-warnaserror[+|-]:<список_чисел> Обрабатывать все предупреждения как ошибки. +-ruleset:<файл> Указать файл набора правил, который отключает определенную диагностику. -errorlog:<файл>[,version=<версия_sarif>] - Указать файл для записи всех диагностических данных компилятора и анализатора - в формате SARIF. + Указать файл для записи всех диагностических данных компилятора + и анализатора в формате SARIF. версия_sarif:{1|2|2.1} По умолчанию: 1. 2 и 2.1 означают SARIF версии 2.1.0. --reportanalyzer Передавать дополнительные сведения о анализаторе, например +-reportanalyzer Сообщить дополнительные сведения об анализаторе, например, время выполнения. -skipanalyzers[+|-] Пропустить выполнение диагностических анализаторов. - ЯЗЫК - --define:<список_символов> Объявить глобальные символы условной - компиляции. список_символов:имя=значение,... +-define:<список_символов> Объявить глобальные символы условной компиляции + symbol(s). список_символов:имя=значение,... (Краткая форма: -d) -imports:<список_импорта> Объявить глобальные импорты для пространств имен в указанных файлах метаданных. - список_импорта:пространство имен,... --langversion:? Показать допустимые значения версии языка --langversion:<строка> Указать версию языка, например - "default" (последняя основная версия) или + import_list:namespace,... +-langversion:? Отображать допустимые значения версии языка +-langversion:<строка> Указать версию языка, например, + "default" (последняя основная версия), или "latest" (последняя версия, включая дополнительные версии), - также можно указывать определенные версии, например "14" или "15.3" --optionexplicit[+|-] Требовать явное объявление переменных. --optioninfer[+|-] Разрешить определение типа переменных. --rootnamespace:<строка> Указать корневое пространство имен для всех объявлений + или определенную версию, например, "14" или "15.3" +-optionexplicit[+|-] Требовать явного объявления переменных. +-optioninfer[+|-] Разрешить определение типа переменных. +-rootnamespace:<строка> Корневое пространство имен для всех объявлений типов. --optionstrict[+|-] Принудительное применение строгой семантики языка. +optionstrict[+|-] Принудительное применение строгой семантики языка. -optionstrict:custom Предупреждать о несоблюдении строгой семантики языка. --optioncompare:binary Сравнение строк в двоичном формате. - Это значение используется по умолчанию. --optioncompare:text Указывает сравнения строк в виде текста. +-optioncompare:binary Задает сравнение строк в двоичном формате. + Это параметр по умолчанию. +-optioncompare:text Задает сравнение строк в виде текста. - ПРОЧЕЕ - --help Отобразить это сообщение об использовании. (Краткая форма: -?) --noconfig Не включать файл VBC.RSP автоматически. --nologo Не показывать баннер со сведениями об авторских правах на компилятор. +-help Отображать сообщение об использовании. (Краткая форма: -?) +-noconfig Не включать в состав файл VBC.RSP автоматически. +-nologo Не отображать баннер компилятора со сведениями об авторских правах. -quiet Режим тихого вывода. -verbose Показать подробные сообщения. -parallel[+|-] Параллельная сборка. --version Показать номер версии компилятора и выйти. +-version Показать номер версии компилятора и выйти. - - РАСШИРЕННЫЕ - + - РАСШИРЕННЫЙ - -baseaddress:<число> Базовый адрес библиотеки или модуля (шестнадцатеричный). --checksumalgorithm:<алгоритм> Указать алгоритм для вычисления контрольной суммы исходного файла, - хранящейся в PDB. Поддерживаемые значения: +-checksumalgorithm:<alg> Указать алгоритм вычисления контрольной суммы + исходного файла, хранящегося в PDB. Поддерживаемые значения: SHA1 или SHA256 (по умолчанию). --codepage:<число> Указать кодовую страницу, используемую при открытии +-codepage:<число> Указывает кодовую страницу, используемую при открытии исходных файлов. --delaysign[+|-] Задержка подписания сборки с использованием только открытой +-delaysign[+|-] Отложенная подпись сборки с использованием только общедоступной части ключа строгого имени. --publicsign[+|-] Открытое подписание сборки с использованием только открытой +-publicsign[+|-] Открытое подписание сборки с использованием только общедоступной части ключа строгого имени. -errorreport:<строка> Указать порядок обработки внутренних ошибок - компилятора; должно быть значение prompt, send, none или queue + компилятора; допустимые значения: prompt, send, none или queue (по умолчанию). --filealign:<число> Указать выравнивание для секций - выходного файла. +-generatedfilesout:<dir> Разместить файлы, созданные во время компиляции в + указанный каталог. +-filealign:<число> Указать выравнивание для секций выходного + файла. -highentropyva[+|-] Включить ASLR с высокой энтропией. --keycontainer:<строка> Указывает контейнер ключей строгого имени. --keyfile:<файл> Указывает файл ключей строгого имени. --libpath:<список_путей> Список каталогов для поиска ссылок на - метаданные. (Разделители — точки с запятыми.) --main:<класс> Указать класс или модуль, содержащий +-keycontainer:<строка> Указывает контейнер ключа строгого имени. +-keyfile:<файл> Указывает файл ключа строгого имени. +-libpath:<список_путей> Список каталогов для поиска ссылок + на метаданные. (Разделитель — точка с запятой.) +-main:<класс> Указывает класс или модуль, содержащий Sub Main. Также можно указать класс, наследующий от System.Windows.Forms.Form. (Краткая форма: -m) --moduleassemblyname:<строка> Имя сборки, в состав которой войдет этот - модуль. +-moduleassemblyname:<строка> Имя сборки, частью которого будет + данный модуль. -netcf Целевая среда — .NET Compact Framework. -nostdlib Не ссылаться на стандартные библиотеки - (system.dll и файл VBC.RSP). + (system.dll и файл VBC. RSP). -pathmap:<K1>=<V1>,<K2>=<V2>,... Указать сопоставление для вывода имен исходных путей компилятором. -platform:<строка> Ограничить платформы, на которых может выполняться этот код; допустимые значения: x86, x64, Itanium, arm, arm64 AnyCPU32BitPreferred или anycpu (по умолчанию). --preferreduilang Указать предпочитаемое имя выходного языка. +-preferreduilang Указать предпочитаемое имя языка вывода. -nosdkpath Отключить поиск стандартных сборок библиотек в пути SDK по умолчанию. --sdkpath:<путь> Расположение каталога SDK .NET Framework +-sdkpath:<путь> Местоположение каталога .NET Framework SDK (mscorlib.dll). --subsystemversion:<версия> Указать версию выходной PE. - версия:<число>[.<число>] --utf8output[+|-] Выводить выходные данные компилятора в кодировке +-subsystemversion:<версия> Указать версию подсистемы выходного PE-файла. + version:<номер>[.<номер>] +-utf8output[+|-] Выдавать выходные данные компилятора в кодировке UTF-8. @<файл> Вставить параметры командной строки из текстового файла -vbruntime[+|-|*] Компилировать со средой выполнения Visual Basic по умолчанию или без нее. --vbruntime:<file> Компилировать с альтернативной средой выполнения Visual Basic +-vbruntime:<файл> Компилировать со средой выполнения Visual Basic в <файле>. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index 0b695b86603a5..d6d0fce63e880 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -269,169 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Visual Basic Derleyici Seçenekleri + Visual Basic Derleyicisi Seçenekleri - ÇIKIŞ DOSYASI - --out:<file> Çıkış dosyasının adını belirtir. +-out:<file> Çıkış dosyası adını belirtir. -target:exe Konsol uygulaması oluşturur (varsayılan). - (Kısa biçim: -t) --target:winexe Windows uygulaması oluşturun. --target:library Kitaplık derlemesi oluşturun. --target:module Bir derlemeye eklenebilen bir dosya - oluşturun. --target:appcontainerexe AppContainer’da çalışan bir Windows uygulaması - oluşturun. --target:winmdobj Windows Meta Veri ara dosyası oluşturun --doc[+|-] XML belge dosyası oluşturur. --doc:<file> <file> dosyasına XML belge dosyası oluşturur. --refout:<file> Oluşturulacak derleme çıkışına başvurun + (Kısa biçimi: -t) +-target:winexe Windows uygulaması oluşturur. +-target:library Kitaplık derlemesi oluşturur. +-target:module Bir derlemeye eklenebilecek bir modül + oluşturur. +-target:appcontainerexe AppContainer içinde çalışan bir Windows uygulaması + oluşturur. +-target:winmdobj Bir Windows Meta Veri ara dosyası oluşturur +-doc[+|-] XML belgeleri dosyası oluşturur. +-doc:<file> <file> için XML belgeleri dosyası oluşturur. +-refout:<file> Oluşturulacak başvuru derlemesi çıkışı - GİRİŞ DOSYALARI - --addmodule:<file_list> Belirtilen modüllerden meta verilere başvurun --link:<file_list> Belirtilen birlikte çalışma derlemesinden meta verileri - ekleyin. (Kısa biçim: -l) --recurse:<wildcard> Joker karakter belirtimlerine göre geçerli dizindeki - ve alt dizinlerdeki tüm - dosyaları ekleyin. --reference:<file_list> Belirtilen derlemeden meta verilere - başvurun. (Kısa biçim: -r) --analyzer:<file_list> Bu derlemeden çözümleyicileri çalıştırın - (Kısa biçim: -a) --additionalfile:<file list> Kod oluşturmayı doğrudan etkilemeyen - ancak hatalar veya uyarılar oluşturarak çözümleyiciler tarafından - kullanılabilen ek dosyalar. +-addmodule:<file_list> Belirtilen modüllerdeki başvuru meta verileri +-link:<file_list> Belirtilen birlikte çalışma derlemesinden meta veri + ekler. (Kısa biçimi: -l) +-recurse:<wildcard> Joker karakter belirtimlerine göre + geçerli dizindeki ve alt dizinlerdeki tüm + dosyaları ekler. +-reference:<file_list> Belirtilen derlemedeki başvuru + meta verileri. (Kısa biçimi: -r) +-analyzer:<file_list> Bu derlemedeki çözümleyicileri çalıştırır + (Kısa biçimi: -a) +-additionalfile:<file list> Kod oluşturmayı doğrudan etkilemeyen ancak + hata veya uyarı üretimi için çözümleyiciler tarafından kullanılabilen + ek dosyalar. - KAYNAKLAR - --linkresource:<resinfo> Belirtilen dosyayı dış derleme kaynağı - olarak ekler. +-linkresource:<resinfo> Belirtilen dosyayı bir dış derleme kaynağı + olarak bağlar. resinfo:<file>[,<name>[,public|private]] - (Kısa biçim: -linkres) --nowin32manifest Varsayılan bildirimin, çıkış PE’sinin bildirim bölümünde - eklenmemesi gerekir. + (Kısa biçimi: -linkres) +-nowin32manifest Varsayılan bildirim çıkış PE’sinin bildirim bölümüne + eklenmemeli. -resource:<resinfo> Belirtilen dosyayı ekli bir derleme kaynağı olarak ekler. resinfo:<file>[,<name>[,public|private]] - (Kısa biçim: -res) --win32icon:<file> Varsayılan Win32 kaynakları için bir Win32 - simge dosyası (.ico) belirtir. --win32manifest:<file> Sağlanan dosya, çıkış PE’sinin - bildirim bölümüne eklenir. + (Kısa biçimi: -res) +-win32icon:<file> Varsayılan Win32 kaynakları için bir + Win32 simge dosyası (.ico) belirtir. +-win32manifest:<file> Sağlanan dosya çıkış PE’sinin bildirim bölümüne + eklenir. -win32resource:<file> Bir Win32 kaynak dosyası (.res) belirtir. - KOD OLUŞTURMA - --optimize[+|-] İyileştirmeleri etkinleştirin. --removeintchecks[+|-] Tamsayı denetimlerini kaldırın. Varsayılan kapalı. --debug[+|-] Hata ayıklama bilgilerini yayın. --debug:full Tam hata ayıklama bilgilerini yayın (varsayılan). --debug:pdbonly Tam hata ayıklama bilgilerini yayın. --debug:portable Platformlar arası hata ayıklama bilgilerini yayın. --debug:embedded Platformlar arası hata ayıklama bilgilerini - hedef .dll veya .exe dosyasına yayın. --deterministic Belirlenimci bir derleme oluşturun - (modül sürümü GUID’i ve zaman damgası dahil) --refonly Ana çıkış yerine bir başvuru derlemesi oluşturun --instrument:TestCoverage Kapsam bilgilerini toplamak için bir - izlenen derleme oluşturun --sourcelink:<file> PDB’ye eklenecek kaynak bağlantı bilgileri. +-optimize[+|-] İyileştirmeleri etkinleştirir. +-removeintchecks[+|-] Tamsayı denetimlerini kaldırır. Varsayılan olarak kapalıdır. +-debug[+|-] Hata ayıklama bilgilerini gösterir. +-debug:full Hata ayıklama bilgilerini tam gösterir (varsayılan). +-debug:pdbonly Hata ayıklama bilgilerini tam gösterir. +-debug:portable Farklı platformlardaki hata ayıklama bilgilerini gösterir. +-debug:embedded Farklı platformlardaki hata ayıklama bilgilerini hedef + .dll veya .exe dosyasında gösterir. +-deterministic Belirlenimci bir derleme üretir + (modül sürümü GUID'si ve zaman damgası dahil) +-refonly Ana çıkış yerine bir başvuru derlemesi üretir +-instrument:TestCoverage Kapsam bilgilerini toplamak için işaretlenmiş + bir derleme üretir +-sourcelink:<file> PDB dosyasına eklenecek kaynak bağlantısı bilgileri. - - HATALAR VE UYARILAR - --nowarn Tüm uyarıları devre dışı bırakın. --nowarn:<number_list> Tek tek uyarıların listesini devre dışı bırakın. --warnaserror[+|-] Tüm uyarıları hata olarak değerlendirin. --warnaserror[+|-]:<number_list> Uyarıların bir listesini hata olarak değerlendirin. --ruleset:<file> Belirli tanılamaları devre dışı bırakan bir kural listesi dosyası - belirtin. + - HATALAR VE UYARILAR - +-nowarn Tüm uyarıları devre dışı bırakır. +-nowarn:<number_list> Uyarıların bir kısmını devre dışı bırakır. +-warnaserror[+|-] Tüm uyarıları hata olarak değerlendirir. +-warnaserror[+|-]:<number_list> Uyarıların bir kısmını hata olarak değerlendirir. +-ruleset:<file> Belirli tanılamaları devre dışı bırakan bir + kural kümesi dosyası belirtir. -errorlog:<file>[,version=<sarif_version>] - Tüm derleyici ve çözümleyici tanılamalarını - SARIF biçiminde günlüğe kaydetmek için bir dosya belirtin. - sarif_version:{1|2|2.1} Varsayılan 1. 2 ve 2.1 - SARIF sürüm 2.1.0’dır. + Tüm derleyici ve çözümleyici tanılamalarının SARIF + biçiminde günlüğe kaydedilmesi için bir dosya belirtir. + sarif_version:{1|2|2.1} Varsayılan olarak 1. 2 ve 2.1 + Her ikisi ise 2.1.0 SARIF sürümünü ifade eder. -reportanalyzer Yürütme zamanı gibi ek çözümleyici bilgilerini - raporlayın. --skipanalyzers[+|-] Tanılama çözümleyicilerinin yürütülmesini atlayın. + raporlar. +-skipanalyzers[+|-] Tanılama çözümleyicilerinin yürütülmesini atlar. - - DİL - --define:<symbol_list> Genel koşullu derleme sembollerini - bildirin. symbol_list:name=value,... - (Kısa biçim: -d) --imports:<import_list> Başvurulan meta veri dosyalarındaki - ad alanları için genel Alımları bildirin. + - DİL - +-define:<symbol_list> Genel koşullu derlemeyi bildirir + symbol(s). symbol_list:name=value,... + (Kısa biçimi: -d) +-imports:<import_list> Başvurulan meta veri dosyalarında ad alanları + için genel İçeri Aktarma işlemlerini bildirir. import_list:namespace,... --langversion:? Dil sürümü için izin verilen değerleri görüntüleyin --langversion:<string> Dil sürümünü - `default` (en son birincil sürüm), veya - `latest` (ikincil sürümler dahil en son sürüm), - ya da `14` veya `15.3` gibi belirli sürümler olarak belirtin --optionexplicit[+|-] Değişkenlerin açıkça bildirilmesini gerektirin. --optioninfer[+|-] Değişkenlerin tür çıkarımına izin verin. +-langversion:? Dil sürümü için izin verilen değerleri görüntüler +-langversion:<string> `default` (en son birincil sürüm) veya + `latest` (ikincil sürümler dahil en son sürüm) veya + `14` veya `15.3` gibi belirli sürümler gibi + dil sürümünü belirtir. +-optionexplicit[+|-] Değişkenlerin açıkça bildirilmesini gerektirir. +-optioninfer[+|-] Değişkenlerin tür çıkarımına izin verir. -rootnamespace:<string> Tüm tür bildirimleri için kök Ad Alanını belirtir. --optionstrict[+|-] Katı dil semantiğini zorunlu kılın. --optionstrict:custom Katı dil semantiğine uyulmadığı zaman - uyar. --optioncompare:binary İkili stilde dize karşılaştırmalarını belirtir. +-optionstrict[+|-] Kesin dil semantik kurallarının uygulanmasını zorlar. +-optionstrict:custom Kesin dil semantik kurallarına uyulmadığında + uyarır. +-optioncompare:binary İkili stilinde dize karşılaştırmaları yapılacağını belirtir. Bu varsayılandır. --optioncompare:text Metin stili dize karşılaştırmalarını belirtir. +-optioncompare:text Metin stilinde dize karşılaştırmaları yapılacağını belirtir. - - ÇEŞİTLİ - --help Bu kullanım iletisini görüntüleyin. (Kısa biçim: -?) + - DİĞER - +-help Bu kullanım iletisini görüntüler. (Kısa biçimi: -?) -noconfig VBC.RSP dosyasını otomatik olarak ekleme. --nologo Derleyici telif hakkı başlığını görüntüleme. +-nologo Derleyici telif hakkı başlığını gösterme. -quiet Sessiz çıkış modu. --verbose Ayrıntılı iletiler görüntüle. +-verbose Ayrıntılı iletileri görüntüler. -parallel[+|-] Eş zamanlı derleme. --version Derleyici sürüm numarasını göster ve çık. +-version Derleyici sürüm numarasını görüntüler ve çıkar. - - GELİŞMİŞ - --baseaddress:<number> Bir kitaplık veya modül için taban adres + - GELİŞMİŞ - +-baseaddress:<number> Kitaplık veya modülün temel adresi (onaltılık). --checksumalgorithm:<alg> PDB dosyasında depolanan hesaplama kaynak dosyası sağlama toplamı için - algoritmayı belirtin. Desteklenen değerler: +-checksumalgorithm:<alg> PDB dosyasında depolanan kaynak dosya + sağlama toplamını hesaplamak için kullanılan algoritmayı belirtir. Desteklenen değerler şunlardır: SHA1 veya SHA256 (varsayılan). --codepage:<number> Kaynak dosyalar açılırken kullanılacak - kod sayfasını belirtir. --delaysign[+|-] Tanımlayıcı ad anahtarının yalnızca genel bölümünü kullanarak - derlemeyi gecikmeli imzala. --publicsign[+|-] Tanımlayıcı ad anahtarının yalnızca genel bölümünü kullanarak - derlemeyi genel olarak imzala. --errorreport:<string> Dahili derleyici hatalarının nasıl işleneceğini - belirtir; prompt, send, none veya queue seçeneklerinden biri olmalıdır - (varsayılan). --filealign:<number> Çıkış dosyası bölümleri için kullanılacak hizalamayı - belirtin. --highentropyva[+|-] Yüksek entropili ASLR’yi etkinleştirin. --keycontainer:<string> Tanımlayıcı ad anahtar dosyası belirtir. --keyfile:<file> Tanımlayıcı ad anahtarı dosyası belirtir. --libpath:<path_list> Meta veri başvurularının aranacağı dizinlerin - listesi. (Noktalı virgülle ayrılmış.) +-codepage:<number> Kaynak dosyalar açılırken kullanılan kod sayfasını + belirtir. +-delaysign[+|-] Tanımlayıcı ad anahtarının ortak bölümünü kullanarak + derlemeyi gecikmeli imzalar. +-publicsign[+|-] Tanımlayıcı ad anahtarının ortak bölümünü kullanarak + derlemeyi genel imzalar. +-errorreport:<string> İç derleyici hatalarının nasıl işleneceğini belirtir; + prompt, send, none veya queue (varsayılan) + olmalıdır. +-generatedfilesout:<dir> Derleme sırasında oluşturulan dosyaları + belirtilen dizinde yerleştirir. +-filealign:<number> Çıkış dosyası bölümleri için kullanılan hizalamayı + belirtir. +-highentropyva[+|-] Yüksek entropili ASLR’yi etkinleştirir. +-keycontainer:<string> Tanımlayıcı ad anahtarı kapsayıcısını belirtir. +-keyfile:<file> Tanımlayıcı ad anahtarı dosyasını belirtir. +-libpath:<path_list> Meta veri başvurularını aramak için kullanılacak + dizinlerin listesi. (Noktalı virgülle ayrılmış.) -main:<class> Alt Ana dosyayı içeren Sınıfı veya Modülü - belirtir. System.Windows.Forms.Form öğesinden - devralan bir sınıf da olabilir. - (Kısa biçim: -m) + belirtir. Bu ayrıca System.Windows.Forms.Form’dan + devralan bir Sınıf da olabilir. + (Kısa biçimi: -m) -moduleassemblyname:<string> Bu modülün bir parçası olacağı derlemenin adı. --netcf .NET Compact Framework’ü hedefleyin. --nostdlib Standart kitaplıklara başvurmayın - (system.dll ve VBC.RSP dosyası). +-netcf .NET Compact Framework'ü hedefler. +-nostdlib Standart kitaplıklara (system.dll ve VBC.RSP dosyası) + başvurma. -pathmap:<K1>=<V1>,<K2>=<V2>,... - Derleyiciye göre kaynak yol adları için - eşleme belirtin. --platform:<string> Kodun çalışabileceği platformları sınırlandırın; - x86, x64, Itanium, arm, arm64 olmalıdır - AnyCPU32BitPreferred veya anycpu (varsayılan). --preferreduilang Tercih edilen çıkış dili adını belirtin. --nosdkpath Standart kitaplık derlemeleri için varsayılan SDK yolunu aramayı devre dışı bırakın. + Derleyicinin oluşturduğu kaynak yol adları için + eşleştirme belirtir. +-platform:<string> Bu kodun çalışabileceği platformları sınırlar; + x86, x64, Itanium, arm, arm64 + AnyCPU32BitPreferred veya anycpu (varsayılan) olmalıdır. +-preferreduilang Tercih edilen çıkış dili adını belirtir. +-nosdkpath Standart kitaplık derlemeleri için varsayılan SDK yolunu aramayı devre dışı bırakır. -sdkpath:<path> .NET Framework SDK dizininin konumu (mscorlib.dll). --subsystemversion:<version> Çıkış PE’sinin alt sistem sürümünü belirtin. +-subsystemversion:<version> Çıkış PE’sinin alt sistem sürümünü belirtir. version:<number>[.<number>] --utf8output[+|-] Derleyici çıkışını UTF-8 karakter kodlamasında - yayın. -@<file> Metin dosyasından komut satırı ayarları ekleyin --vbruntime[+|-|*] Varsayılan Visual Basic çalışma zamanıyla/çalışma zamanı olmadan - derleyin. --vbruntime:<file> <file> içinde alternatif Visual Basic - çalışma zamanıyla derleyin. +-utf8output[+|-] Derleyici çıkışını UTF-8 karakter kodlamasıyla + gösterir. +@<file> Komut satırı ayarlarını metin dosyasından alarak ekler +-vbruntime[+|-|*] Varsayılan Visual Basic çalışma zamanı ile/olmadan + derler. +-vbruntime:<file> <file> içindeki alternatif Visual Basic çalışma zamanı ile + derler. diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf index 71bd20f7eeb40..958e0be310564 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hans.xlf @@ -269,169 +269,179 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Visual Basic 编译器选项 + Visual Basic 编译器选项 - - OUTPUT FILE - + - 输出文件 - -out:<file> 指定输出文件名。 -target:exe 创建控制台应用程序(默认)。 - (Short form: -t) + (缩写: -t) -target:winexe 创建 Windows 应用程序。 -target:library 创建库程序集。 --target:module 创建可添加到 - 程序集的模块。 --target:appcontainerexe 创建可在 - AppContainer 中运行的 Windows 应用程序。 --target:winmdobj 创建 Windows 元数据中间文件。 +-target:module 创建可添加到 + 的模块 + 程序集。 +-target:appcontainerexe 创建在 + 中运行的 Windows 应用程序 + AppContainer。 +-target:winmdobj 创建 Windows 元数据中间文件 -doc[+|-] 生成 XML 文档文件。 --doc:<file> 生成 XML 文档文件到 <file>。 --refout:<file> 可生成的引用程序集输出 +-doc:<file> 将 XML 文档文件生成到 <file>。 +-refout:<file> 引用要生成的程序集输出 - - INPUT FILES - --addmodule:<file_list> 来自指定模块的引用元数据 --link:<file_list> 从指定互操作 - 程序集嵌入元数据。(Short form: -l) --recurse:<wildcard> 根据通配符规范 - 在当前目录和子目录中 - 中包含所有文件。 --reference:<file_list> 来自指定程序集的 - 引用元数据。(Short form: -r) --analyzer:<file_list> 从此程序集运行分析器 - (Short form: -a) --additionalfile:<file list> 不直接影响代码生成但是可能由分析器用于产生 - 错误或警告的 - 其他文件。 + - 输入文件 - +-addmodule:<file_list> 从指定模块引用元数据 +-link:<file_list> 从指定的互操作嵌入元数据 + 程序集。(缩写: -l) +-recurse:<wildcard> 包括当前目录中的所有文件 + 和子目录,根据 + 通配符规范。 +-reference:<file_list> 指定 +的引用元数据 + 程序集。(缩写: -r) +-analyzer:<file_list> 从此程序集中运行分析器 + (缩写: -a) +-additionalfile:<file list> 不会直接影响代码的其他文件 + 生成,但可由分析器用于生成 + 错误或警告。 - - RESOURCES - --linkresource:<resinfo> 将指定的文件 - 链接为外部程序集资源。 - resinfo:<file>[,<name>[,public|private]] - (Short form: -linkres) --nowin32manifest 不应在输出 PE 的清单节中 - 嵌入默认清单。 --resource:<resinfo> 将指定的文件添加为 - 嵌入的程序集资源。 - resinfo:<file>[,<name>[,public|private]] - (Short form: -res) --win32icon:<file> 为默认的 Win32 资源 - 指定一个 Win32 icon 文件(.ico)。 --win32manifest:<file> 提供的文件嵌入在 - 输出 PE 的清单节中。 --win32resource:<file> 指定一个 Win32 资源文件(.res)。 + - 资源 - +-linkresource:<resinfo> 将指定文件链接为外部文件 + 程序集资源。 + resinfo:<file>[,<name>[,public|private]] + (缩写: -linkres) +-nowin32manifest 默认清单不应嵌入 + 在输出 PE 的清单部分中。 +-resource:<resinfo> 将指定的文件添加为嵌入式 + 程序集资源。 + resinfo:<file>[,<name>[,public|private]] + (缩写: -res) +-win32icon:<file> 为 +指定 Win32 图标文件 (.ico) + 默认 Win32 资源。 +-win32manifest:<file> 提供的文件嵌入清单 + 输出 PE 的一部分。 +-win32manifest:<file> 指定 Win32 资源文件 (.res)。 - - CODE GENERATION - + - 代码生成 - -optimize[+|-] 启用优化。 -removeintchecks[+|-] 删除整数检查。默认关闭。 -debug[+|-] 发出调试信息。 --debug:full 发出完整调试信息(默认)。 --debug:pdbonly 发出完整调试信息。 +-debug:full 发出完全调试信息(默认)。 +-debug:pdbonly 发出完整的调试信息。 -debug:portable 发出跨平台调试信息。 --debug:embedded 发出跨平台调试信息到 - 目标 .dll 或 .exe。 --deterministic 生成确定性的程序集 - (包含模块版本 GUID 和时间戳) --refonly 在主输出的位置中生成引用程序集 --instrument:TestCoverage 生成收集覆盖信息的 - 程序集 --sourcelink:<file> 要嵌入到 PDB 中的源链接信息。 +-debug:embedded 将跨平台调试信息发出到 + 目标 .dll 或 .exe。 +-deterministic 生成确定性程序集 + (包括模块版本 GUID 和时间戳) +-refonly 生成引用程序集来代替主输出 +-instrument:TestCoverage 生成检测到收集的程序集 + 覆盖范围信息 +-sourcelink:<file> 源链接信息以嵌入 PDB。 - - 错误和警告 - + - 错误和警告 - -nowarn 禁用所有警告。 --nowarn:<number_list> 禁用一列单个警告。 +-nowarn:<number_list> 禁用单个警告的列表。 -warnaserror[+|-] 将所有警告视为错误。 --warnaserror[+|-]:<number_list> 将一列警告视为错误。 --ruleset:<file> 指定禁用特定 - 诊断的规则集文件。 +-warnaserror[+|-]:<number_list> 将警告列表视为错误。 +-ruleset:<file> 指定禁用特定规则集文件 + 诊断。 -errorlog:<file>[,version=<sarif_version>] - 指定一个文件,以 SARIF 格式 - 记录所有编译器和分析器。 - sarif_version:{1|2|2.1} 默认为 1. 2 和 2.1 - 两者都意为 SARIF 版本 2.1.0。 --reportanalyzer 报告其他分析器信息,如 - 执行时间。 + 指定用于记录所有编译器和分析器的文件 + SARIF 格式的诊断。 + sarif_version:{1|2|2.1} 默认值为 1。2 和 2.1 + 均表示 SARIF 版本 2.1.0。 +-reportanalyzer 报告其他分析器信息,例如 + 执行时间。 -skipanalyzers[+|-] 跳过诊断分析器的执行。 - - LANGUAGE - + - 语言 - -define:<symbol_list> 声明全局条件编译 - 符号。 symbol_list:name=value,... - (Short form: -d) --imports:<import_list> 声明引用的元数据文件中的 - 命名空间的全局导入。 - import_list:namespace,... + symbol(s). symbol_list:name=value,... + (缩写: -d) +-imports:<import_list> 声明命名空间的全局导入 + 引用的元数据文件。 + import_list:namespace,... -langversion:? 显示语言版本的允许值 -langversion:<string> 指定语言版本,如 - `default` (最新的主要版本)或 - `latest` (最新版本,包括次要版本) - 或具体版本,如 `14` 或 `15.3` --optionexplicit[+|-] 需要变量的显式声明。 + `default`(最新主版本),或 + `latest`(最新版本,包括次要版本), + 或特定版本,如 `14` 或 `15.3` +-o-optionexplicit[+|-] 需要显式声明变量。 -optioninfer[+|-] 允许变量的类型推理。 --rootnamespace:<string> 指定所有类型声明的 - 根命名空间。 --optionstrict[+|-] 强制执行严格的语言语义。 --optionstrict:custom 当严格的语言语义未得到遵守时 - 发出警告。 +-rootnamespace:<string> 指定所有类型声明的根命名空间 + 声明。 +-optionstrict[+|-] 强制实施严格的语言语义。 +-optionstrict:custom 当严格语言语义不严格时自定义警告 + 遵守。 -optioncompare:binary 指定二进制样式字符串比较。 - 这是默认项。 + 这是默认值。 -optioncompare:text 指定文本样式字符串比较。 - - MISCELLANEOUS - --help 显示此使用情况消息。(Short form: -?) --noconfig 请勿自动包含 VBC.RSP 文件。 --nologo 请勿显示编译器版权横幅。 --quiet 免打扰输出模式。 + - 其他 - +-help 显示此用法消息。(短格式: -?) +-noconfig 不自动包含 VBC.RSP 文件。 +-nologo 不显示编译器版权标题。 +-quiet 静默输出模式。 -verbose 显示详细消息。 --parallel[+|-] 并发版本。 +-parallel[+|-] 并发生成。 -version 显示编译器版本号并退出。 - - ADVANCED - --baseaddress:<number> 库或模块的基础地址 - (hex)。 --checksumalgorithm:<alg> 指定计算 PDB 中存储的 - 源文件校验和的算法。支持的值为: - SHA1 或 SHA256 (默认)。 --codepage:<number> 指定打开文件时 - 要使用的代码页。 + - 高级 - +-baseaddress:<number> 库或模块的基址 + (十六进制)。 +-checksumalgorithm:<alg> 指定用于计算源文件 +的算法 + 存储在 PDB 中的校验和。支持的值为: + SHA1 或 SHA256 (默认值)。 +-codepage:<number> 指定打开时要使用的代码页 + 源文件。 -delaysign[+|-] 仅使用强名称密钥的公共部分 - portion of 延迟签名程序集。 --publicsign[+|-] 仅使用强名称密钥的公共部分 - 公共签名程序集。 + 强名称键的一部分。 +-publicsign[+|-] 仅使用公共对程序集进行公共签名 + 强名称键的一部分。 -errorreport:<string> 指定如何处理内部编译器 - 错误; 必须为提示、发送、无、排队 - (默认)。 --filealign:<number> 指定为输出文件部分使用的 - 对齐。 + 错误; 必须是提示、发送、无或队列 + (默认)。 +-generatedfilesout:<dir> 将编译期间生成的文件放在 + 指定的目录。 +-filealign:<number> 指定用于输出文件的对齐方式 + 节数。 -highentropyva[+|-] 启用高熵 ASLR。 -keycontainer:<string> 指定强名称密钥容器。 -keyfile:<file> 指定强名称密钥文件。 --libpath:<path_list> 供搜索元数据引用的 - 目录列表。(用分号分割。) --main:<class> 指定包含 Sub Main 的 - Class 或 Module。也可以是 - 继承自 System.Windows.Forms.Form 的 Class。 - (简短形式: -m) --moduleassemblyname:<string> 此模块所属的程序集的 - 名称。 +-libpath:<path_list> 要搜索元数据的目录列表 + 引用。(分号分隔。) +-main:<class> 指定包含 +的类或模块 + 子主控件。它也可以是一个类, + 继承自 System.Windows.Forms.Form。 + (缩写: -m) +-moduleassemblyname:<string> 此模块将 +的程序集的名称 + 成为其中的一部分。 -netcf 面向 .NET Compact Framework。 --nostdlib 请勿引用标准库 - (system.dll 和 VBC.RSP 文件)。 +-nostdlib 不引用标准库 + (system.dll 和 VBC.RSP 文件)。 -pathmap:<K1>=<V1>,<K2>=<V2>,... - 指定编译器的源路径名称输出的 - 映射。 --platform:<string> 限制可以运行此代码的平台; - 必须为 x86、x64、Itanium、arm、arm64 - AnyCPU32BitPreferred 或 anycpu (默认)。 --preferreduilang 指定偏好的输出语言名称。 + 通过 +指定源路径名称输出的映射 + 编译器。 +-platform:<string> 限制此代码可以在哪些平台上运行; + 必须是 x86、x64、Itanium、arm、arm64 + AnyCPU32BitPreferred 或 anycpu (默认值)。 +--preferreduilang 指定首选输出语言名称。 -nosdkpath 禁用搜索标准库程序集的默认 SDK 路径。 --sdkpath:<path> .NET Framework SDK 目录 - (mscorlib.dll)的位置。 +-sdkpath:<path> .NET Framework SDK 目录的位置 + (mscorlib.dll)。 -subsystemversion:<version> 指定输出 PE 的子系统版本。 - version:<number>[.<number>] --utf8output[+|-] 以 UTF-8 字符编码格式 - 发出编译器输出。 -@<file> 从文本文件 --vbruntime[+|-|*] 插入命令行设置 在有/没有默认 Visual Basic 运行时的情况下 - 进行编译。 --vbruntime:<file> 使用 <file> 中的替代 Visual Basic 运行时 - 进行编译。 + version:<number>[.<number>] +-utf8output[+|-] 以 UTF-8 字符发出编译器输出 + 编码。 +@<file> 从文本文件插入命令行设置 +-vbruntime[+|-|*] 使用/不使用默认 Visual Basic 运行时编译 + 运行时。 +-vbruntime:<file> 使用备用 Visual Basic 运行时编译 + <文件>中的运行时。 diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index 420734271fadf..414bb417104d8 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -269,169 +269,171 @@ -vbruntime:<file> Compile with the alternate Visual Basic runtime in <file>. - Visual Basic 編譯器選項 + Visual Basic 編譯器選項 - - OUTPUT FILE - + - OUTPUT FILE - -out:<file> 指定輸出檔案名稱。 --target:exe 建立主控台應用程式 (預設值)。 - (簡短格式: -t) +-target:exe 建立主控台應用程式 (預設)。 + (簡短形式: -t) -target:winexe 建立 Windows 應用程式。 -target:library 建立程式庫組件。 --target:module 建立可新增至組件的 - 模組。 --target:appcontainerexe 建立在 AppContainer 中執行的 - Windows 應用程式。 +-target:module 建立可新增到 + 組件的模組。 +-target:appcontainerexe 建立可在 AppContainer 中執行的 + Windows 應用程式。 -target:winmdobj 建立 Windows 中繼資料中繼檔案 --doc[+|-] 產生 XML 文件檔。 --doc:<file> 產生 XML 文件檔至 <file>。 --refout:<file> 參考要產生的組件輸出 +-doc[+|-] 產生 XML 文件檔案。 +-doc:<file> 產生 XML 文件檔案至 <file>。 +-refout:<file> 要產生的參考組件輸出 - - INPUT FILES - --addmodule:<file_list> 參考來自指定模組的中繼資料 --link:<file_list> 內嵌來自指定 Interop 組件的 - 中繼資料。(簡短格式: -l) --recurse:<wildcard> 根據萬用字元規格,包含 - 目前目錄和子目錄中的 - 所有檔案。 --reference:<file_list> 參考來自指定組件的 - 中繼資料。(簡短格式: -r) + - INPUT FILES - +-addmodule:<file_list> 從指定的模組參考中繼資料。 +-link:<file_list> 從指定的 Interop + 中繼資料。(簡短形式: -l) +-recurse:<wildcard> 根據萬用字元規格 + 包含目前目錄和子目錄 + 中的所有檔案。 +-reference:<file_list> 從指定的組件參考 + 中繼資料。(簡短形式: -r) -analyzer:<file_list> 從此組件執行分析器 - (簡短格式: -a) --additionalfile:<file list> 不直接影響程式碼產生 - 但可能會被分析器用來產生錯誤或警告的 - 的其他檔案。 + (簡短形式: -a) +-additionalfile:<file list> 不會影響程式碼產生 + 但可由分析器用來產生錯誤或警告 + 的其他檔案。 - - RESOURCES - --linkresource:<resinfo> 將指定的檔案連結為外部 - 組件資源。 - resinfo:<file>[,<name>[,public|private]] - (簡短格式: -linkres) --nowin32manifest 預設的資訊清單不應內嵌在 - 輸出 PE 的資訊清單區段。 --resource:<resinfo> 將指定的檔案新增為內嵌的 - 組件資源。 - resinfo:<file>[,<name>[,public|private]] - (簡短格式: -res) --win32icon:<file> 指定預設 Win32 資源的 Win32 圖示 - 檔案 (.ico)。 --win32manifest:<file> 提供的檔案內嵌在輸出 PE 的 - 資訊清單區段。 + - RESOURCES - +-linkresource:<resinfo> 連結指定的檔案做為外部檔案 + 組件資源。 + resinfo:<file>[,<name>[,public|private]] + (簡短形式: -linkres) +-nowin32manifest 預設資訊清單不應該內嵌在 + 輸出 PE 的資訊清單區段。 +-resource:<resinfo> 將指定的檔案新增為內嵌 + 組件資源。 + resinfo:<file>[,<name>[,public|private]] + (簡短形式: -res) +-win32icon:<file> 為預設 Win32 資源指定 + Win32 圖示檔案 (.ico)。 +-win32manifest:<file> 提供的檔案內嵌在 + 輸出 PE 的資訊清單區段。 -win32resource:<file> 指定 Win32 資源檔案 (.res)。 - - CODE GENERATION - + - CODE GENERATION - -optimize[+|-] 啟用最佳化。 --removeintchecks[+|-] 移除整數檢查。預設關閉。 --debug[+|-] 發出完整偵錯資訊。 +-removeintchecks[+|-] 移除整數檢查。預設為關閉。 +-debug[+|-] 發出偵錯資訊。 -debug:full 發出完整偵錯資訊 (預設)。 -debug:pdbonly 發出完整偵錯資訊。 -debug:portable 發出跨平台偵錯資訊。 --debug:embedded 發出跨平台偵錯資訊到 - 目標 .dll 或 .exe。 --deterministic 產生確定性組件 - (包括模組版本 GUID 和時間戳記) --refonly 產生參考組件取代主要輸出 --instrument:TestCoverage 產生檢測的組件以收集 - 涵蓋範圍資訊 --sourcelink:<file> 要內嵌到 PDB 的來源連結資訊。 +-debug:embedded 發出跨平台偵錯資訊至 + 目標 .dll 或 .exe。 +-deterministic 產生具決定性組件 + (包括模組版本 GUID 和時間戳記) +-refonly 產生參考組件,以取代主要輸出 +-instrument:TestCoverage 產生檢測要收集 + 涵蓋範圍資訊的組件 +-sourcelink:<file> 要內嵌至 PDB 的來源連結資訊。 - - ERRORS AND WARNINGS - + - ERRORS AND WARNINGS - -nowarn 停用所有警告。 -nowarn:<number_list> 停用個別警告的清單。 -warnaserror[+|-] 將所有警告視為錯誤。 -warnaserror[+|-]:<number_list> 將警告清單視為錯誤。 --ruleset:<file> 指定停用特定診斷的規則集 - 檔案。 +-ruleset:<file> 指定會停用特定診斷的 + 規則集檔案。 -errorlog:<file>[,version=<sarif_version>] - 指定要以 SARIF 格式記錄所有編譯器和 - 分析器診斷的檔案。 - sarif_version:{1|2|2.1} 預設值為 1。2 和 2.1 - 兩者都表示 SARIF 版本 2.1.0。 + 指定用來以 SARIF 格式記錄所有編譯器和分析器診斷 + 的檔案。 + sarif_version:{1|2|2.1} 預設為 1。2 和 2.1 + 都表示 SARIF 版本 2.1.0。 -reportanalyzer 報告其他分析器資訊,例如 - 執行時間。 --skipanalyzers[+|-] 略過執行診斷分析器。 + 執行時間。 +-skipanalyzers[+|-] 略過診斷分析器執行。 - - LANGUAGE - + - LANGUAGE - -define:<symbol_list> 宣告全域條件式編譯 - 符號。symbol_list:name=value,... - (簡短格式: -d) --imports:<import_list> 在參考的中繼資料檔案中宣告命名空間的 - 全域匯入。 - import_list:namespace,... --langversion:? 顯示允許的語言版本值 + 符號。symbol_list:name=value,... + (簡短形式: -d) +-imports:<import_list> 在參考的中繼資料檔案中 + 宣告命名空間的全域匯入。 + import_list:namespace,... +-langversion:? 顯示語言版本的允許值 -langversion:<string> 指定語言版本,例如 - `default` (最新主要版本),或 - `latest` (最新版本,包括次要版本), - 或特定版本,例如 `14` 或 `15.3` + `default` (最新的主要版本),或 + `latest` (最新版本,包括次要版本), + 或特定版本,例如 `14` 或 `15.3` -optionexplicit[+|-] 需要明確宣告變數。 --optioninfer[+|-] 允許型別推斷變數。 --rootnamespace:<string> 指定所有型別宣告的根 - 命名空間。 --optionstrict[+|-] 強制執行嚴格的語言語意學。 --optionstrict:custom 在未遵守嚴格的語言語意學時 - 警告。 +-optioninfer[+|-] 允許變數的類型推斷。 +-rootnamespace:<string> 指定所有類型宣告 + 的根命名空間。 +-optionstrict[+|-] 強制執行嚴格的語言語意。 +-optionstrict:custom 未遵守嚴格的語言語意時警告 + 。 -optioncompare:binary 指定二進位樣式字串比較。 - 這是預設值。 + 這是預設值。 -optioncompare:text 指定文字樣式字串比較。 - - MISCELLANEOUS - --help 顯示此使用方式訊息。(簡短格式: -?) --noconfig 不要自動納入 VBC.RSP 檔。 --nologo 不要顯示編譯器著作權橫幅。 --quiet 無對話輸出模式。 --verbose 顯示詳細訊息。 --parallel[+|-] 同時組建。 --version 顯示編譯器版本號碼並結束。 + - MISCELLANEOUS - +-help 顯示使用方式訊息。(簡短形式: -?) +-noconfig 不要自動包括 VBC.RSP 檔案。 +-nologo 不要顯示編譯器著作權橫幅。 +-quiet 無訊息輸出模式。 +-verbose 顯示詳細訊息。 +-parallel[+|-] 並行建置。 +-version 顯示編譯器版本號碼並結束。 - - ADVANCED - -- baseaddress:<number> 程式庫或模組的基底位址 (Base Address) - (十六進位)。 --checksumalgorithm:<alg> 指定計算儲存在 PDB 中原始程式檔 - 檢查碼的演算法。支援的值為: - SHA1 或 SHA256 (預設值)。 --codepage:<number> 指定開啟原始程式檔時使用的 - 字碼頁。 --delayign[+|-] 只使用強式名稱金鑰的公用 - 部分延遲簽署組件。 --publicsign[+|-] 只使用強式名稱金鑰的公用 - 部分公開簽署組件。 + - ADVANCED - +-baseaddress:<number> 程式庫或模組的基本位址 + (十六進位)。 +-checksumalgorithm:<alg> 指定計算儲存在 PDB 中 + 來源檔案總和檢查碼的演算法。支援的值包括: + SHA1 或 SHA256 (預設)。 +-codepage:<number> 指定開啟來源檔案時 + 要使用的字碼頁。 +-delaysign[+|-] 只使用強式名稱金鑰的公開 + 部分延遲為組件簽章簽署。 +-publicsign[+|-] 只使用強式名稱金鑰的公開 + 部分公開為組件簽章簽署。 -errorreport:<string> 指定如何處理內部編譯器 - 錯誤; 必須是 prompt、send、none 或 queue - (預設值)。 --filealign:<number> 指定用於輸出檔案區段的對齊 - 方式。 --highentropyva[+|-] 啟用高熵 ASLR。 --keycontainer:<string> 指定強式名稱金鑰容器。 --keyfile:<file> 指定強式名稱金鑰檔案。 --libpath:<path_list> 要搜尋中繼資料參考的目錄 - 清單。(以分號分隔。) --main:<class> 指定包含 Sub Main 的 - Class 或 Module。它也可以是繼承自 - System.Windows.Forms.Form 的 Class。 - (簡短格式: -m) --moduleassemblyname:<string> 此模組將成為其中一部分的 - 組件的名稱。 + 錯誤; 必須是提示、傳送、無或佇列 + (預設)。 +-generatedfilesout:<dir> 將編譯期間產生的檔案放在 + 指定的目錄。 +-filealign:<number> 指定用於輸出檔案 + 區段的對齊。 +-highentropyva[+|-] 啟用高熵 ASLR。 +-keycontainer:<string> 指定強式名稱金鑰容器。 +-keyfile:<file> 指定強式名稱金鑰檔案。 +-libpath:<path_list> 用於搜尋中繼資料 + 參考的目錄清單。(以分號分隔。) +-main:<class> 指定包含 + Sub Main 的類別或模組。它也可以是 + 繼承自 System.Windows.Forms.Form 的類別。 + (簡短形式: -m) +-moduleassemblyname:<string> 此模組將成為 + 其一部分的組件名稱。 -netcf 以 .NET Compact Framework 為目標。 --nostdlib 不要參考標準程式庫 - (system.dll 和 VBC.RSP 檔)。 +-nostdlib 不參考標準程式庫 + (system.dll 和 VBC.RSP 檔案)。 -pathmap:<K1>=<V1>,<K2>=<V2>,... - 由編譯器指定來源路徑名稱輸出的 - 對應。 + 指定編譯器的來源路徑名稱輸出的對應 + 。 -platform:<string> 限制此程式碼可在哪些平台上執行; - 必須是 x86、x64、Itanium、arm、arm64 - AnyCPU32BitPreferred 或 anycpu (預設值)。 --preferreduilang 指定喜好的輸出語言名稱。 --nosdkpath 停用搜尋標準程式庫組件的預設 SDK 路徑。 --sdkpath:<path> .NET Framework SDK 目錄位置 - (mscorlib.dll)。 --subsystemversion:<version> 指定輸出 PE 版本的子系統版本。 - version:<number>[.<number>] + 必須是 x86、x64、Itanium、arm、arm64 + AnyCPU32BitPreferred 或 anycpu (預設)。 +-preferreduilang 指定偏好的輸出語言名稱。 +-nosdkpath 停用搜尋標準程式庫組件的預設 SDK 路徑。 +-sdkpath:<path> .NET Framework SDK 目錄的位置 + (mscorlib.dll)。 +-subsystemversion:<version> 指定輸出 PE 的子系統版本。 + version:<number>[.<number>] -utf8output[+|-] 以 UTF-8 字元編碼 - 發出編譯器輸出。 -@<file> 從文字檔插入命令列設定 --vbruntime[+|-|*] 使用/不使用預設的 Visual Basic - 執行階段編譯。 --vbruntime:<file> 在 <file> 中以替代的 Visual Basic - 執行階段編譯。 + 發出編譯器輸出。 +@<file> 從文字檔插入命令列設定 +-vbruntime[+|-|*] 使用/不使用預設 Visual Basic + 執行階段編譯。 +-vbruntime:<file> 使用 <file> 中的其他 Visual Basic + 執行階段編譯。 diff --git a/src/Dependencies/PooledObjects/ArrayBuilder.cs b/src/Dependencies/PooledObjects/ArrayBuilder.cs index d9bb084a1bf28..5cc2144a932aa 100644 --- a/src/Dependencies/PooledObjects/ArrayBuilder.cs +++ b/src/Dependencies/PooledObjects/ArrayBuilder.cs @@ -7,6 +7,10 @@ using System.Collections.Immutable; using System.Diagnostics; +#if COMPILERCORE +using Roslyn.Utilities; +#endif + namespace Microsoft.CodeAnalysis.PooledObjects { [DebuggerDisplay("Count = {Count,nq}")] diff --git a/src/EditorFeatures/Core.Wpf/StringIndentation/StringIndentationTaggerProvider.cs b/src/EditorFeatures/Core.Wpf/StringIndentation/StringIndentationTaggerProvider.cs index 0fd160f9185cd..822049d448840 100644 --- a/src/EditorFeatures/Core.Wpf/StringIndentation/StringIndentationTaggerProvider.cs +++ b/src/EditorFeatures/Core.Wpf/StringIndentation/StringIndentationTaggerProvider.cs @@ -32,11 +32,11 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.StringIndentation /// /// This factory is called to create taggers that provide information about how strings are indented. /// - [Export(typeof(ITaggerProvider))] + [Export(typeof(IViewTaggerProvider))] [TagType(typeof(StringIndentationTag))] [VisualStudio.Utilities.ContentType(ContentTypeNames.CSharpContentType)] [VisualStudio.Utilities.ContentType(ContentTypeNames.VisualBasicContentType)] - internal sealed partial class StringIndentationTaggerProvider : AsynchronousTaggerProvider + internal sealed partial class StringIndentationTaggerProvider : AsynchronousViewTaggerProvider { private readonly IEditorFormatMap _editorFormatMap; @@ -73,11 +73,29 @@ internal sealed partial class StringIndentationTaggerProvider : AsynchronousTagg protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeInclusive; protected override ITaggerEventSource CreateEventSource( - ITextView? textView, ITextBuffer subjectBuffer) + ITextView textView, ITextBuffer subjectBuffer) { + // Note: we don't listen for OnTextChanged. They'll get reported by the ViewSpan changing. return TaggerEventSources.Compose( - new EditorFormatMapChangedEventSource(_editorFormatMap), - TaggerEventSources.OnTextChanged(subjectBuffer)); + TaggerEventSources.OnViewSpanChanged(ThreadingContext, textView), + new EditorFormatMapChangedEventSource(_editorFormatMap)); + } + + protected override IEnumerable GetSpansToTag(ITextView? textView, ITextBuffer subjectBuffer) + { + this.ThreadingContext.ThrowIfNotOnUIThread(); + Contract.ThrowIfNull(textView); + + // Find the visible span some 100 lines +/- what's actually in view. This way + // if the user scrolls up/down, we'll already have the results. + var visibleSpanOpt = textView.GetVisibleLinesSpan(subjectBuffer, extraLines: 100); + if (visibleSpanOpt == null) + { + // Couldn't find anything visible, just fall back to tagging all brace locations + return base.GetSpansToTag(textView, subjectBuffer); + } + + return SpecializedCollections.SingletonEnumerable(visibleSpanOpt.Value); } protected override async Task ProduceTagsAsync( diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionPriorityProvider.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionPriorityProvider.cs new file mode 100644 index 0000000000000..9e3194ee53e52 --- /dev/null +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionPriorityProvider.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Diagnostics; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions; + +internal sealed class SuggestedActionPriorityProvider : ICodeActionRequestPriorityProvider +{ + /// + /// Set of de-prioritized analyzers that were moved down from 'Normal' to 'Low' + /// priority bucket. + /// Note that this set is owned by the + /// and shared across priority buckets. + /// + private readonly ConcurrentSet _lowPriorityAnalyzers; + + public SuggestedActionPriorityProvider(CodeActionRequestPriority priority, ConcurrentSet lowPriorityAnalyzers) + { + Priority = priority; + _lowPriorityAnalyzers = lowPriorityAnalyzers; + } + + public CodeActionRequestPriority Priority { get; } + + public void AddDeprioritizedAnalyzerWithLowPriority(DiagnosticAnalyzer analyzer) + => _lowPriorityAnalyzers.Add(analyzer); + + public bool IsDeprioritizedAnalyzerWithLowPriority(DiagnosticAnalyzer analyzer) + => _lowPriorityAnalyzers.Contains(analyzer); +} diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs index 5e2d3023080a5..40e2bd4688400 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; @@ -217,25 +218,28 @@ private static string GetFixCategory(DiagnosticSeverity severity) CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { + var lowPriorityAnalyzers = new ConcurrentSet(); + foreach (var order in Orderings) { var priority = TryGetPriority(order); Contract.ThrowIfNull(priority); + var priorityProvider = new SuggestedActionPriorityProvider(priority.Value, lowPriorityAnalyzers); - var result = await GetFixLevelAsync(priority.Value).ConfigureAwait(false); + var result = await GetFixLevelAsync(priorityProvider).ConfigureAwait(false); if (result != null) return result; } return null; - async Task GetFixLevelAsync(CodeActionRequestPriority priority) + async Task GetFixLevelAsync(ICodeActionRequestPriorityProvider priorityProvider) { if (state.Target.Owner._codeFixService != null && state.Target.SubjectBuffer.SupportsCodeFixes()) { var result = await state.Target.Owner._codeFixService.GetMostSevereFixAsync( - document, range.Span.ToTextSpan(), priority, fallbackOptions, cancellationToken).ConfigureAwait(false); + document, range.Span.ToTextSpan(), priorityProvider, fallbackOptions, cancellationToken).ConfigureAwait(false); if (result.HasFix) { diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource_Async.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource_Async.cs index 81c577728fc60..fee59d8d3620c 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource_Async.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource_Async.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.Shared; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; @@ -103,6 +104,12 @@ private partial class SuggestedActionsSource : IAsyncSuggestedActionsSource var pendingActionSets = new MultiDictionary(); + // Keep track of the diagnostic analyzers that have been deprioritized across calls to the + // diagnostic engine. We'll run them once we get around to the low-priority bucket. We want to + // keep track of this *across* calls to each priority. So we create this set outside of the loop and + // then pass it continuously from one priority group to the next. + var lowPriorityAnalyzers = new ConcurrentSet(); + // Collectors are in priority order. So just walk them from highest to lowest. foreach (var collector in collectors) { @@ -112,7 +119,7 @@ private partial class SuggestedActionsSource : IAsyncSuggestedActionsSource state, requestedActionCategories, document, range, selection, addOperationScope: _ => null, - priority, + new SuggestedActionPriorityProvider(priority, lowPriorityAnalyzers), currentActionCount, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false); await foreach (var set in allSets) @@ -179,7 +186,7 @@ await foreach (var set in allSets) SnapshotSpan range, TextSpan? selection, Func addOperationScope, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, int currentActionCount, [EnumeratorCancellation] CancellationToken cancellationToken) { @@ -218,7 +225,7 @@ Task> GetCodeFixesAsync() return UnifiedSuggestedActionsSource.GetFilterAndOrderCodeFixesAsync( workspace, owner._codeFixService, document, range.Span.ToTextSpan(), - priority, options, addOperationScope, cancellationToken).AsTask(); + priorityProvider, options, addOperationScope, cancellationToken).AsTask(); } Task> GetRefactoringsAsync() @@ -239,7 +246,7 @@ Task> GetRefactoringsAsync() // 'CodeActionRequestPriority.Lowest' is reserved for suppression/configuration code fixes. // No code refactoring should have this request priority. - if (priority == CodeActionRequestPriority.Lowest) + if (priorityProvider.Priority == CodeActionRequestPriority.Lowest) return SpecializedTasks.EmptyImmutableArray(); // If we are computing refactorings outside the 'Refactoring' context, i.e. for example, from the lightbulb under a squiggle or selection, @@ -247,7 +254,7 @@ Task> GetRefactoringsAsync() var filterOutsideSelection = !requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring); return UnifiedSuggestedActionsSource.GetFilterAndOrderCodeRefactoringsAsync( - workspace, owner._codeRefactoringService, document, selection.Value, priority, options, + workspace, owner._codeRefactoringService, document, selection.Value, priorityProvider.Priority, options, addOperationScope, filterOutsideSelection, cancellationToken); } diff --git a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs index 81599278e29ec..9e16ec6f63df9 100644 --- a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs +++ b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs @@ -12,6 +12,8 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Diagnostics.EngineV2; +using Microsoft.CodeAnalysis.Editor.Implementation.Suggestions; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.ErrorLogger; @@ -19,6 +21,7 @@ using Microsoft.CodeAnalysis.Extensions; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; @@ -63,7 +66,7 @@ public async Task TestGetFirstDiagnosticWithFixAsync() var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference); var document = project.Documents.Single(); var unused = await fixService.GetMostSevereFixAsync( - document, TextSpan.FromBounds(0, 0), CodeActionRequestPriority.None, CodeActionOptions.DefaultProvider, CancellationToken.None); + document, TextSpan.FromBounds(0, 0), new DefaultCodeActionRequestPriorityProvider(), CodeActionOptions.DefaultProvider, CancellationToken.None); var fixer1 = (MockFixer)fixers.Single().Value; var fixer2 = (MockFixer)reference.Fixers.Single(); @@ -148,14 +151,14 @@ public async Task TestGetFixesAsyncForFixableAndNonFixableAnalyzersAsync() // Verify only analyzerWithFix is executed when GetFixesAsync is invoked with 'CodeActionRequestPriority.Normal'. _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), - priority: CodeActionRequestPriority.Normal, CodeActionOptions.DefaultProvider, + priorityProvider: new DefaultCodeActionRequestPriorityProvider(CodeActionRequestPriority.Normal), CodeActionOptions.DefaultProvider, addOperationScope: _ => null, cancellationToken: CancellationToken.None); Assert.True(analyzerWithFix.ReceivedCallback); Assert.False(analyzerWithoutFix.ReceivedCallback); // Verify both analyzerWithFix and analyzerWithoutFix are executed when GetFixesAsync is invoked with 'CodeActionRequestPriority.Lowest'. _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), - priority: CodeActionRequestPriority.Lowest, CodeActionOptions.DefaultProvider, + priorityProvider: new DefaultCodeActionRequestPriorityProvider(CodeActionRequestPriority.Lowest), CodeActionOptions.DefaultProvider, addOperationScope: _ => null, cancellationToken: CancellationToken.None); Assert.True(analyzerWithFix.ReceivedCallback); Assert.True(analyzerWithoutFix.ReceivedCallback); @@ -184,7 +187,7 @@ public async Task TestGetFixesAsyncForDocumentDiagnosticAnalyzerAsync() // Verify both analyzers are executed when GetFixesAsync is invoked with 'CodeActionRequestPriority.Normal'. _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), - priority: CodeActionRequestPriority.Normal, CodeActionOptions.DefaultProvider, + priorityProvider: new DefaultCodeActionRequestPriorityProvider(CodeActionRequestPriority.Normal), CodeActionOptions.DefaultProvider, addOperationScope: _ => null, cancellationToken: CancellationToken.None); Assert.True(documentDiagnosticAnalyzer.ReceivedCallback); } @@ -293,7 +296,7 @@ private static async Task GetFirstDiagnosticWithFixWithExceptionValidationAsync( GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager); var unused = await tuple.codeFixService.GetMostSevereFixAsync( - document, TextSpan.FromBounds(0, 0), CodeActionRequestPriority.None, CodeActionOptions.DefaultProvider, CancellationToken.None); + document, TextSpan.FromBounds(0, 0), new DefaultCodeActionRequestPriorityProvider(), CodeActionOptions.DefaultProvider, CancellationToken.None); Assert.True(extensionManager.IsDisabled(codefix)); Assert.False(extensionManager.IsIgnored(codefix)); Assert.True(errorReported); @@ -303,22 +306,22 @@ private static async Task GetFirstDiagnosticWithFixWithExceptionValidationAsync( CodeFixProvider codefix, bool includeConfigurationFixProviders = false, bool throwExceptionInFixerCreation = false, - TestHostDocument? additionalDocument = null) - => ServiceSetup(ImmutableArray.Create(codefix), includeConfigurationFixProviders, throwExceptionInFixerCreation, additionalDocument); + TestHostDocument? additionalDocument = null, + string code = "class Program { }") + => ServiceSetup(ImmutableArray.Create(codefix), includeConfigurationFixProviders, throwExceptionInFixerCreation, additionalDocument, code); private static (TestWorkspace workspace, DiagnosticAnalyzerService analyzerService, CodeFixService codeFixService, IErrorLoggerService errorLogger) ServiceSetup( ImmutableArray codefixers, bool includeConfigurationFixProviders = false, bool throwExceptionInFixerCreation = false, - TestHostDocument? additionalDocument = null) + TestHostDocument? additionalDocument = null, + string code = "class Program { }") { var fixers = codefixers.Select(codefix => new Lazy( () => throwExceptionInFixerCreation ? throw new Exception() : codefix, new CodeChangeProviderMetadata("Test", languages: LanguageNames.CSharp))); - var code = @"class Program { }"; - var workspace = TestWorkspace.CreateCSharp(code, composition: s_compositionWithMockDiagnosticUpdateSourceRegistrationService, openDocuments: true); if (additionalDocument != null) { @@ -354,12 +357,22 @@ private static async Task GetFirstDiagnosticWithFixWithExceptionValidationAsync( out TextDocument document, out EditorLayerExtensionManager.ExtensionManager extensionManager, MockAnalyzerReference? analyzerReference = null, + TextDocumentKind documentKind = TextDocumentKind.Document) + => GetDocumentAndExtensionManager(diagnosticService, workspace, out document, out extensionManager, out _, analyzerReference, documentKind); + + private static void GetDocumentAndExtensionManager( + DiagnosticAnalyzerService diagnosticService, + TestWorkspace workspace, + out TextDocument document, + out EditorLayerExtensionManager.ExtensionManager extensionManager, + out DiagnosticIncrementalAnalyzer diagnosticIncrementalAnalyzer, + MockAnalyzerReference? analyzerReference = null, TextDocumentKind documentKind = TextDocumentKind.Document) { var incrementalAnalyzer = (IIncrementalAnalyzerProvider)diagnosticService; // register diagnostic engine to solution crawler - _ = incrementalAnalyzer.CreateIncrementalAnalyzer(workspace); + diagnosticIncrementalAnalyzer = (DiagnosticIncrementalAnalyzer)incrementalAnalyzer.CreateIncrementalAnalyzer(workspace)!; var reference = analyzerReference ?? new MockAnalyzerReference(); var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference); @@ -924,5 +937,247 @@ internal sealed class AdditionalFileFixerWithoutDocumentKindsAndExtensions : Abs public AdditionalFileFixerWithoutDocumentKindsAndExtensions() : base(nameof(AdditionalFileFixerWithoutDocumentKindsAndExtensions)) { } } #pragma warning restore RS0034 // Exported parts should be marked with 'ImportingConstructorAttribute' + + [Theory, CombinatorialData] + public async Task TestGetFixesWithDeprioritizedAnalyzerAsync( + DeprioritizedAnalyzer.ActionKind actionKind, + bool testWithCachedDiagnostics, + bool diagnosticOnFixLineInPriorSnapshot, + bool editOnFixLine, + bool addNewLineWithEdit) + { + // This test validates analyzer de-prioritization logic in diagnostic service for lightbulb code path. + // Basically, we have a certain set of heuristics (detailed in the next comment below), under which an analyzer + // which is deemed to be an expensive analyzer is moved down from 'Normal' priority code fix bucket to + // 'Low' priority bucket to improve lightbulb performance. This test validates this logic by performing + // the following steps: + // 1. Use 2 snapshots of document, such that the analyzer has a reported diagnostic on the code fix trigger + // line in the earlier snapshot based on the flag 'diagnosticOnFixLineInPriorSnapshot' + // 2. For the second snapshot, mimic whether or not background analysis has computed and cached full document + // diagnostics for the document based on the flag 'testWithCachedDiagnostics'. + // 3. Apply an edit in the second snapshot on the code fix trigger line based on the flag 'editOnFixLine'. + // If this flag is false, edit is apply at a different line in the document. + // 4. Add a new line edit in the second snapshot based on the flag 'addNewLineWithEdit'. This tests the part + // of the heuristic where we compare intersecting diagnostics across document snapshots only if both + // snapshots have the same number of lines. + + var expectDeprioritization = GetExpectDeprioritization(actionKind, testWithCachedDiagnostics, diagnosticOnFixLineInPriorSnapshot, addNewLineWithEdit); + + var priorSnapshotFixLine = diagnosticOnFixLineInPriorSnapshot ? "int x1 = 0;" : "System.Console.WriteLine();"; + var code = $@" +#pragma warning disable CS0219 +class C +{{ + void M() + {{ + {priorSnapshotFixLine} + }} +}}"; + + var codeFix = new FixerForDeprioritizedAnalyzer(); + var analyzer = new DeprioritizedAnalyzer(actionKind); + var analyzerReference = new MockAnalyzerReference(codeFix, ImmutableArray.Create(analyzer)); + + var tuple = ServiceSetup(codeFix, code: code); + using var workspace = tuple.workspace; + GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, + out var extensionManager, out var diagnosticIncrementalAnalyzer, analyzerReference); + + var sourceDocument = (Document)document; + var root = await sourceDocument.GetRequiredSyntaxRootAsync(CancellationToken.None); + var testSpan = diagnosticOnFixLineInPriorSnapshot + ? root.DescendantNodes().OfType().First().Span + : root.DescendantNodes().OfType().First().Span; + + // Trigger background analysis to ensure analyzer diagnostics are computed and cached. + // We enable full solution analysis so the 'AnalyzeDocumentAsync' doesn't skip analysis based on whether the document is active/open. + workspace.GlobalOptions.SetGlobalOption(SolutionCrawlerOptionsStorage.BackgroundAnalysisScopeOption, LanguageNames.CSharp, BackgroundAnalysisScope.FullSolution); + await diagnosticIncrementalAnalyzer.AnalyzeDocumentAsync(sourceDocument, bodyOpt: null!, InvocationReasons.DocumentChanged, CancellationToken.None); + await VerifyCachedDiagnosticsAsync(sourceDocument, expectedCachedDiagnostic: diagnosticOnFixLineInPriorSnapshot, testSpan, diagnosticIncrementalAnalyzer); + + // Compute and apply code edit + if (editOnFixLine) + { + code = code.Replace(priorSnapshotFixLine, "int x2 = 0;"); + } + else + { + code += " // Comment at end of file"; + } + + if (addNewLineWithEdit) + { + // Add a new line at the start of the document to ensure the line with diagnostic in prior snapshot moved. + code = Environment.NewLine + code; + } + + sourceDocument = sourceDocument.WithText(SourceText.From(code)); + var appliedChanges = workspace.TryApplyChanges(sourceDocument.Project.Solution); + Assert.True(appliedChanges); + sourceDocument = workspace.CurrentSolution.Projects.Single().Documents.Single(); + + root = await sourceDocument.GetRequiredSyntaxRootAsync(CancellationToken.None); + var expectedNoFixes = !diagnosticOnFixLineInPriorSnapshot && !editOnFixLine; + testSpan = !expectedNoFixes + ? root.DescendantNodes().OfType().First().Span + : root.DescendantNodes().OfType().First().Span; + + if (testWithCachedDiagnostics) + { + // Trigger background analysis to ensure analyzer diagnostics are computed and cached. + await diagnosticIncrementalAnalyzer.AnalyzeDocumentAsync(sourceDocument, bodyOpt: null!, InvocationReasons.DocumentChanged, CancellationToken.None); + await VerifyCachedDiagnosticsAsync(sourceDocument, expectedCachedDiagnostic: !expectedNoFixes, testSpan, diagnosticIncrementalAnalyzer); + } + + var lowPriorityAnalyzers = new ConcurrentSet(); + var priorityProvider = new SuggestedActionPriorityProvider(CodeActionRequestPriority.Normal, lowPriorityAnalyzers); + var normalPriFixes = await tuple.codeFixService.GetFixesAsync(sourceDocument, testSpan, priorityProvider, CodeActionOptions.DefaultProvider, addOperationScope: _ => null, CancellationToken.None); + priorityProvider = new SuggestedActionPriorityProvider(CodeActionRequestPriority.Low, lowPriorityAnalyzers); + var lowPriFixes = await tuple.codeFixService.GetFixesAsync(sourceDocument, testSpan, priorityProvider, CodeActionOptions.DefaultProvider, addOperationScope: _ => null, CancellationToken.None); + + if (expectedNoFixes) + { + Assert.Empty(normalPriFixes); + Assert.Empty(lowPriFixes); + return; + } + + CodeFixCollection expectedFixCollection; + if (expectDeprioritization) + { + Assert.Empty(normalPriFixes); + expectedFixCollection = Assert.Single(lowPriFixes); + var lowPriorityAnalyzer = Assert.Single(lowPriorityAnalyzers); + Assert.Same(analyzer, lowPriorityAnalyzer); + } + else + { + expectedFixCollection = Assert.Single(normalPriFixes); + Assert.Empty(lowPriFixes); + Assert.Empty(lowPriorityAnalyzers); + } + + var fix = expectedFixCollection.Fixes.Single(); + Assert.Equal(FixerForDeprioritizedAnalyzer.Title, fix.Action.Title); + return; + + static bool GetExpectDeprioritization( + DeprioritizedAnalyzer.ActionKind actionKind, + bool testWithCachedDiagnostics, + bool diagnosticOnFixLineInPriorSnapshot, + bool addNewLineWithEdit) + { + // We expect de-prioritization of analyzer from 'Normal' to 'Low' bucket only if following conditions are met: + // 1. There are no cached diagnostics from background analysis, i.e. 'testWithCachedDiagnostics == false'. + // 2. We have an expensive analyzer that registers SymbolStart/End or SemanticModel actions, both of which have a broad analysis scope. + // 3. Either of the below is true: + // a. We do not have an analyzer diagnostic reported in the prior document snapshot on the edited line OR + // b. Number of lines in the prior document snapshot differs from number of lines in the current document snapshot, + // i.e. we added a new line with the edit and 'addNewLineWithEdit = true'. + + // Condition 1 + if (testWithCachedDiagnostics) + return false; + + // Condition 2 + if (actionKind is not (DeprioritizedAnalyzer.ActionKind.SymbolStartEnd or DeprioritizedAnalyzer.ActionKind.SemanticModel)) + return false; + + // Condition 3(a) + if (!diagnosticOnFixLineInPriorSnapshot) + return true; + + // Condition 3(b) + return addNewLineWithEdit; + } + + static async Task VerifyCachedDiagnosticsAsync(Document sourceDocument, bool expectedCachedDiagnostic, TextSpan testSpan, DiagnosticIncrementalAnalyzer diagnosticIncrementalAnalyzer) + { + var cachedDiagnostics = await diagnosticIncrementalAnalyzer.GetCachedDiagnosticsAsync(sourceDocument.Project.Solution, sourceDocument.Project.Id, sourceDocument.Id); + if (!expectedCachedDiagnostic) + { + Assert.Empty(cachedDiagnostics); + } + else + { + var diagnostic = Assert.Single(cachedDiagnostics); + Assert.Equal(DeprioritizedAnalyzer.Descriptor.Id, diagnostic.Id); + var text = await sourceDocument.GetTextAsync(); + Assert.Equal(testSpan, diagnostic.DataLocation.UnmappedFileSpan.GetClampedTextSpan(text)); + } + } + } + + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class DeprioritizedAnalyzer : DiagnosticAnalyzer + { + public enum ActionKind + { + SymbolStartEnd, + SemanticModel, + Operation + } + + public static readonly DiagnosticDescriptor Descriptor = new("ID0001", "Title", "Message", "Category", DiagnosticSeverity.Warning, isEnabledByDefault: true); + private readonly ActionKind _actionKind; + + public DeprioritizedAnalyzer(ActionKind actionKind) + { + _actionKind = actionKind; + } + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + switch (_actionKind) + { + case ActionKind.SymbolStartEnd: + context.RegisterSymbolStartAction(context => + { + var variableDeclarations = new HashSet(); + context.RegisterOperationAction(context + => variableDeclarations.Add(context.Operation.Syntax), OperationKind.VariableDeclaration); + context.RegisterSymbolEndAction(context => + { + foreach (var decl in variableDeclarations) + context.ReportDiagnostic(Diagnostic.Create(Descriptor, decl.GetLocation())); + }); + }, SymbolKind.NamedType); + break; + + case ActionKind.SemanticModel: + context.RegisterSemanticModelAction(context => + { + var variableDeclarations = context.SemanticModel.SyntaxTree.GetRoot().DescendantNodes().OfType(); + foreach (var decl in variableDeclarations) + context.ReportDiagnostic(Diagnostic.Create(Descriptor, decl.GetLocation())); + }); + break; + + case ActionKind.Operation: + context.RegisterOperationAction(context => + context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Operation.Syntax.GetLocation())), + OperationKind.VariableDeclaration); + break; + } + } + } + + private sealed class FixerForDeprioritizedAnalyzer : CodeFixProvider + { + public static readonly string Title = $"Fix {DeprioritizedAnalyzer.Descriptor.Id}"; + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DeprioritizedAnalyzer.Descriptor.Id); + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.RegisterCodeFix( + CodeAction.Create(Title, + createChangedDocument: _ => Task.FromResult(context.Document), + equivalenceKey: nameof(FixerForDeprioritizedAnalyzer)), + context.Diagnostics); + return Task.CompletedTask; + } + } } } diff --git a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb index 8027a0249bbd1..9aad9c81743ec 100644 --- a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb +++ b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb @@ -2228,7 +2228,7 @@ class C ' Verify diagnostics for span Dim diagnostics = Await diagnosticService.GetDiagnosticsForSpanAsync(document, span, shouldIncludeDiagnostic:=Nothing, - includeCompilerDiagnostics:=True, includeSuppressedDiagnostics:=False, CodeActionRequestPriority.None, + includeCompilerDiagnostics:=True, includeSuppressedDiagnostics:=False, New DefaultCodeActionRequestPriorityProvider(), addOperationScope:=Nothing, DiagnosticKind.All, isExplicit:=False, CancellationToken.None) Dim diagnostic = Assert.Single(diagnostics) Assert.Equal("CS0219", diagnostic.Id) @@ -2236,7 +2236,7 @@ class C ' Verify no diagnostics outside the local decl span span = localDecl.GetLastToken().GetNextToken().GetNextToken().Span diagnostics = Await diagnosticService.GetDiagnosticsForSpanAsync(document, span, shouldIncludeDiagnostic:=Nothing, - includeCompilerDiagnostics:=True, includeSuppressedDiagnostics:=False, CodeActionRequestPriority.None, + includeCompilerDiagnostics:=True, includeSuppressedDiagnostics:=False, New DefaultCodeActionRequestPriorityProvider(), addOperationScope:=Nothing, DiagnosticKind.All, isExplicit:=False, CancellationToken.None) Assert.Empty(diagnostics) End Using diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/MockDiagnosticAnalyzerService.cs b/src/EditorFeatures/TestUtilities/Diagnostics/MockDiagnosticAnalyzerService.cs index f948beffcba38..3f579e5bb9556 100644 --- a/src/EditorFeatures/TestUtilities/Diagnostics/MockDiagnosticAnalyzerService.cs +++ b/src/EditorFeatures/TestUtilities/Diagnostics/MockDiagnosticAnalyzerService.cs @@ -64,7 +64,7 @@ public Task> GetDiagnosticsAsync(Solution solutio public Task> GetDiagnosticsForIdsAsync(Solution solution, ProjectId? projectId = null, DocumentId? documentId = null, ImmutableHashSet? diagnosticIds = null, bool includeSuppressedDiagnostics = false, bool includeNonLocalDocumentDiagnostics = true, CancellationToken cancellationToken = default) => throw new NotImplementedException(); - public Task> GetDiagnosticsForSpanAsync(TextDocument document, TextSpan? range, Func? shouldIncludeDiagnostic, bool includeCompilerDiagnostics, bool includeSuppressedDiagnostics = true, CodeActionRequestPriority priority = CodeActionRequestPriority.None, Func? addOperationScope = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default) + public Task> GetDiagnosticsForSpanAsync(TextDocument document, TextSpan? range, Func? shouldIncludeDiagnostic, bool includeCompilerDiagnostics, bool includeSuppressedDiagnostics = true, ICodeActionRequestPriorityProvider? priorityProvider = null, Func? addOperationScope = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default) => Task.FromResult(_diagnosticsWithKindFilter.Where(d => diagnosticKind == d.KindFilter).Select(d => d.Diagnostic).ToImmutableArray()); public Task> GetProjectDiagnosticsForIdsAsync(Solution solution, ProjectId? projectId = null, ImmutableHashSet? diagnosticIds = null, bool includeSuppressedDiagnostics = false, bool includeNonLocalDocumentDiagnostics = true, CancellationToken cancellationToken = default) @@ -73,7 +73,7 @@ public Task> GetProjectDiagnosticsForIdsAsync(Sol public Task> GetSpecificCachedDiagnosticsAsync(Workspace workspace, object id, bool includeSuppressedDiagnostics = false, bool includeNonLocalDocumentDiagnostics = true, CancellationToken cancellationToken = default) => throw new NotImplementedException(); - public Task<(ImmutableArray diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync(TextDocument document, TextSpan range, Func? shouldIncludeDiagnostic, bool includeSuppressedDiagnostics = false, CodeActionRequestPriority priority = CodeActionRequestPriority.None, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default) + public Task<(ImmutableArray diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync(TextDocument document, TextSpan range, Func? shouldIncludeDiagnostic, bool includeSuppressedDiagnostics = false, ICodeActionRequestPriorityProvider? priorityProvider = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default) => throw new NotImplementedException(); } } diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf index b3bcbe0f7aa44..385157b2f241f 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + vlastnost jenom pro inicializaci diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf index 37d8adac6d3dc..f04c9c227d9e6 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + „init-only“-Eigenschaft diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf index d393bb8749b57..660a58a11d9e1 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + propiedad de solo inicialización diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf index 5d3fa9ffb81cf..c13a02f6383c9 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + propriété init-only diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf index b079a9b8752bc..166db0f0edef7 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + proprietà di sola inizializzazione diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf index 4d04709f92926..7418e02273253 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + init 専用プロパティ diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf index 171153e6219ed..06925c6a22ef5 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + init 전용 속성 diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf index 742669c5184f3..1529d599d29e1 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + właściwość tylko do inicjowania diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf index 39407a87e2e7b..0325f0c2836c4 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + propriedade somente inicialização diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf index 9a5fddae2cc4a..e339d31eed7b4 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + свойство, предназначенное только для инициализации diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf index 523ea6134c353..5a896df056266 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + yalnızca init özelliği diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf index 8de89c00339a0..482b3867c62a1 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + init-only 属性 diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf index 70c18bffe86a1..99f6ee8fb74a4 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf @@ -249,7 +249,7 @@ init-only property - init-only property + init-only 屬性 diff --git a/src/Features/Core/Portable/CodeFixesAndRefactorings/CodeActionRequestPriorityProvider.cs b/src/Features/Core/Portable/CodeFixesAndRefactorings/CodeActionRequestPriorityProvider.cs new file mode 100644 index 0000000000000..162718b770f50 --- /dev/null +++ b/src/Features/Core/Portable/CodeFixesAndRefactorings/CodeActionRequestPriorityProvider.cs @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CodeActions +{ + internal interface ICodeActionRequestPriorityProvider + { + CodeActionRequestPriority Priority { get; } + + /// + /// Tracks the given as a de-prioritized analyzer that should be moved to + /// bucket. + /// + void AddDeprioritizedAnalyzerWithLowPriority(DiagnosticAnalyzer analyzer); + + bool IsDeprioritizedAnalyzerWithLowPriority(DiagnosticAnalyzer analyzer); + } + + internal static class ICodeActionRequestPriorityProviderExtensions + { + /// + /// Returns true if the given can report diagnostics that can have fixes from a code + /// fix provider with matching . This method is useful for performing a performance + /// optimization for lightbulb diagnostic computation, wherein we can reduce the set of analyzers to be executed + /// when computing fixes for a specific . + /// + public static bool MatchesPriority(this ICodeActionRequestPriorityProvider provider, DiagnosticAnalyzer analyzer) + { + var priority = provider.Priority; + + // If caller isn't asking for prioritized result, then run all analyzers. + if (priority == CodeActionRequestPriority.None) + return true; + + // 'CodeActionRequestPriority.Lowest' is used for suppression/configuration fixes, + // which requires all analyzer diagnostics. + if (priority == CodeActionRequestPriority.Lowest) + return true; + + // The compiler analyzer always counts for any priority. It's diagnostics may be fixed + // by high pri or normal pri fixers. + if (analyzer.IsCompilerAnalyzer()) + return true; + + // Check if we are computing diagnostics for 'CodeActionRequestPriority.Low' and + // this analyzer was de-prioritized to low priority bucket. + if (priority == CodeActionRequestPriority.Low && + provider.IsDeprioritizedAnalyzerWithLowPriority(analyzer)) + { + return true; + } + + // Now compute this analyzer's priority and compare it with the provider's request 'Priority'. + // Our internal 'IBuiltInAnalyzer' can specify custom request priority, while all + // the third-party analyzers are assigned 'Normal' priority. + var analyzerPriority = analyzer is IBuiltInAnalyzer { RequestPriority: var requestPriority } + ? requestPriority + : CodeActionRequestPriority.Normal; + + return priority == analyzerPriority; + } + + /// + /// Returns true if the given should be considered a candidate when computing + /// fixes for the given . + /// + public static bool MatchesPriority(this ICodeActionRequestPriorityProvider provider, CodeFixProvider codeFixProvider) + { + if (provider.Priority == CodeActionRequestPriority.None) + { + // We are computing fixes for all priorities + return true; + } + if (provider.Priority == CodeActionRequestPriority.Low) + { + // 'Low' priority can be used for two types of code fixers: + // 1. Those which explicitly set their 'RequestPriority' to 'Low' and + // 2. Those which can fix diagnostics for expensive analyzers which were de-prioritized + // to 'Low' priority bucket to improve lightbulb population performance. + // Hence, when processing the 'Low' Priority bucket, we accept fixers with any RequestPriority, + // as long as they can fix a diagnostic from an analyzer that was executed in the 'Low' bucket. + return true; + } + + return provider.Priority == codeFixProvider.RequestPriority; + } + } + + internal sealed class DefaultCodeActionRequestPriorityProvider : ICodeActionRequestPriorityProvider + { + private readonly object _gate = new(); + private HashSet? _lowPriorityAnalyzers; + + public DefaultCodeActionRequestPriorityProvider(CodeActionRequestPriority priority = CodeActionRequestPriority.None) + { + Priority = priority; + } + + public CodeActionRequestPriority Priority { get; } + + public void AddDeprioritizedAnalyzerWithLowPriority(DiagnosticAnalyzer analyzer) + { + lock (_gate) + { + _lowPriorityAnalyzers ??= new(); + _lowPriorityAnalyzers.Add(analyzer); + } + } + + public bool IsDeprioritizedAnalyzerWithLowPriority(DiagnosticAnalyzer analyzer) + { + lock (_gate) + { + return _lowPriorityAnalyzers != null && _lowPriorityAnalyzers.Contains(analyzer); + } + } + } +} diff --git a/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs b/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs index 94ad6d68a5495..6042eea91d2dc 100644 --- a/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs +++ b/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs @@ -76,13 +76,13 @@ internal interface IDiagnosticAnalyzerService /// This API will only force complete analyzers that support span based analysis, i.e. compiler analyzer and /// s that support . /// For the rest of the analyzers, it will only return diagnostics if the analyzer has already been executed. - /// Use + /// Use /// if you want to force complete all analyzers and get up-to-date diagnostics for all analyzers for the given span. /// Task<(ImmutableArray diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync( TextDocument document, TextSpan range, Func? shouldIncludeDiagnostic, bool includeSuppressedDiagnostics = false, - CodeActionRequestPriority priority = CodeActionRequestPriority.None, + ICodeActionRequestPriorityProvider? priorityProvider = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default); @@ -99,7 +99,7 @@ internal interface IDiagnosticAnalyzerService TextDocument document, TextSpan? range, Func? shouldIncludeDiagnostic, bool includeCompilerDiagnostics, bool includeSuppressedDiagnostics = false, - CodeActionRequestPriority priority = CodeActionRequestPriority.None, + ICodeActionRequestPriorityProvider? priorityProvider = null, Func? addOperationScope = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, @@ -113,7 +113,7 @@ internal static class IDiagnosticAnalyzerServiceExtensions bool includeSuppressedDiagnostics = false, Func? addOperationScope = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default) - => service.GetDiagnosticsForSpanAsync(document, range, diagnosticId, includeSuppressedDiagnostics, CodeActionRequestPriority.None, addOperationScope, diagnosticKind, isExplicit, cancellationToken); + => service.GetDiagnosticsForSpanAsync(document, range, diagnosticId, includeSuppressedDiagnostics, priorityProvider: null, addOperationScope, diagnosticKind, isExplicit, cancellationToken); /// /// Return up to date diagnostics for the given span for the document @@ -126,7 +126,7 @@ internal static class IDiagnosticAnalyzerServiceExtensions public static Task> GetDiagnosticsForSpanAsync(this IDiagnosticAnalyzerService service, TextDocument document, TextSpan? range, string? diagnosticId = null, bool includeSuppressedDiagnostics = false, - CodeActionRequestPriority priority = CodeActionRequestPriority.None, + ICodeActionRequestPriorityProvider? priorityProvider = null, Func? addOperationScope = null, DiagnosticKind diagnosticKind = DiagnosticKind.All, bool isExplicit = false, @@ -134,7 +134,7 @@ internal static class IDiagnosticAnalyzerServiceExtensions { Func? shouldIncludeDiagnostic = diagnosticId != null ? id => id == diagnosticId : null; return service.GetDiagnosticsForSpanAsync(document, range, shouldIncludeDiagnostic, - includeCompilerDiagnostics: true, includeSuppressedDiagnostics, priority, + includeCompilerDiagnostics: true, includeSuppressedDiagnostics, priorityProvider, addOperationScope, diagnosticKind, isExplicit, cancellationToken); } } diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index f311d3c800e89..610091e7fac00 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -342,7 +342,7 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn C# and Visual Basic References - C# and Visual Basic References + Reference pro C# a Visual Basic @@ -612,7 +612,7 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Dekonstruovat místní hodnoty pro {0} @@ -747,7 +747,7 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + Funkce Najít všechny odkazy se nevyvolala u použitelného symbolu. @@ -2692,7 +2692,7 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv This {0} has {1} reference(s). - This {0} has {1} reference(s). + Položka {0} obsahuje tento počet odkazů: {1}. @@ -3127,7 +3127,7 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv {0} reference - {0} reference + Počet odkazů: {0} @@ -3137,7 +3137,7 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv {0} references - {0} references + Počet odkazů: {0} @@ -3549,7 +3549,7 @@ Specifikátor standardního formátu f představuje kombinaci vzorů dlouhého d get-only property - get-only property + vlastnost jenom pro načtení diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index 57c84fd770d70..1e7b8c23e2454 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -342,7 +342,7 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d C# and Visual Basic References - C# and Visual Basic References + Referenzen zu C# und Visual Basic @@ -612,7 +612,7 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Lokale Elemente für „{0}“ dekonstruieren @@ -747,7 +747,7 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + „Alle Verweise suchen“ wurde für das anwendbare Symbol nicht aufgerufen. @@ -2692,7 +2692,7 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg This {0} has {1} reference(s). - This {0} has {1} reference(s). + {0} hat {1} Verweise. @@ -3127,7 +3127,7 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg {0} reference - {0} reference + {0} Verweis @@ -3137,7 +3137,7 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg {0} references - {0} references + {0} Verweise @@ -3549,7 +3549,7 @@ Der Standardformatbezeichner "f" repräsentiert eine Kombination aus den Mustern get-only property - get-only property + „get-only“-Eigenschaft diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index 8f31cf596805d..6d74a5638aa25 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -342,7 +342,7 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa C# and Visual Basic References - C# and Visual Basic References + Referencias de C# y Visual Basic @@ -612,7 +612,7 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Deconstruir variables locales para '{0}' @@ -747,7 +747,7 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 'Buscar todas las referencias' no invocado en el símbolo aplicable @@ -2692,7 +2692,7 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us This {0} has {1} reference(s). - This {0} has {1} reference(s). + El elemento {0} tiene las siguientes referencias: {1}. @@ -3127,7 +3127,7 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us {0} reference - {0} reference + {0} referencia @@ -3137,7 +3137,7 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us {0} references - {0} references + {0} referencias @@ -3549,7 +3549,7 @@ El especificador de formato estándar "f" representa una combinación de los pat get-only property - get-only property + propiedad get-only diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 6af4b917e1873..d2ee2979cf5e8 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -342,7 +342,7 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai C# and Visual Basic References - C# and Visual Basic References + Références C# et Visual Basic @@ -612,7 +612,7 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Déconstruire les variables locales pour '{0}' @@ -747,7 +747,7 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 'Rechercher toutes les références' non appelé sur le symbole applicable @@ -2692,7 +2692,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée This {0} has {1} reference(s). - This {0} has {1} reference(s). + Cette {0} a {1} référence(s). @@ -3127,7 +3127,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée {0} reference - {0} reference + {0} référence @@ -3137,7 +3137,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée {0} references - {0} references + {0} références @@ -3549,7 +3549,7 @@ Le spécificateur de format standard "f" représente une combinaison des modèle get-only property - get-only property + propriété get-only diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index 9c68b05670139..f55b4916436ab 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -342,7 +342,7 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa C# and Visual Basic References - C# and Visual Basic References + Riferimenti per C# e Visual Basic @@ -612,7 +612,7 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Locali di decostruzione per '{0}' @@ -747,7 +747,7 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 'Trova tutti i riferimenti' non richiamato su un simbolo applicabile @@ -2692,7 +2692,7 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' This {0} has {1} reference(s). - This {0} has {1} reference(s). + {0} ha {1} riferimento/i. @@ -3127,7 +3127,7 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' {0} reference - {0} reference + {0} riferimento @@ -3137,7 +3137,7 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' {0} references - {0} references + {0} riferimenti @@ -3549,7 +3549,7 @@ L'identificatore di formato standard "f" rappresenta una combinazione degli sche get-only property - get-only property + proprietà di solo richiamo diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 60632d9841448..dc2b63f081953 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -342,7 +342,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma C# and Visual Basic References - C# and Visual Basic References + C# および Visual Basic の参照 @@ -612,7 +612,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + '{0}' のローカルを分解します @@ -747,7 +747,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 該当するシンボルに対して 'Find All References' が呼び出されていません @@ -2692,7 +2692,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of This {0} has {1} reference(s). - This {0} has {1} reference(s). + この {0} には {1} 個の参照があります。 @@ -3127,7 +3127,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} reference - {0} reference + {0} 個の参照 @@ -3137,7 +3137,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} references - {0} references + {0} 個の参照 @@ -3549,7 +3549,7 @@ The "f" standard format specifier represents a combination of the long date ("D" get-only property - get-only property + get 専用プロパティ diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 49b38ca950c33..957569eb776d0 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -342,7 +342,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma C# and Visual Basic References - C# and Visual Basic References + C# 및 Visual Basic 참조 @@ -612,7 +612,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + '{0}'에 대한 로컬 분해 @@ -747,7 +747,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 해당 기호에서 '모든 참조 찾기'가 호출되지 않음 @@ -2692,7 +2692,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of This {0} has {1} reference(s). - This {0} has {1} reference(s). + 이 {0}에는 {1}개의 참조가 있습니다. @@ -3127,7 +3127,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} reference - {0} reference + 참조 {0}개 @@ -3137,7 +3137,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} references - {0} references + 참조 {0}개 @@ -3549,7 +3549,7 @@ The "f" standard format specifier represents a combination of the long date ("D" get-only property - get-only property + get 전용 속성 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index f533f8b5ba21c..cf05937eef820 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -342,7 +342,7 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k C# and Visual Basic References - C# and Visual Basic References + Dokumentacja języków C# i Visual Basic @@ -612,7 +612,7 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Dekonstrukcja elementów lokalnych dla '{0}' @@ -747,7 +747,7 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + Nie wywołano elementu „Znajdź wszystkie odwołania” dla odpowiedniego symbolu @@ -2692,7 +2692,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk This {0} has {1} reference(s). - This {0} has {1} reference(s). + Liczba odwołań dla {0}: {1}. @@ -3127,7 +3127,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk {0} reference - {0} reference + {0} odwołanie @@ -3137,7 +3137,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk {0} references - {0} references + Odwołania: {0} @@ -3549,7 +3549,7 @@ Standardowy specyfikator formatu „f” reprezentuje połączenie wzorców dłu get-only property - get-only property + własność tylko do uzyskania diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index eefdd1bf46856..eb7311fbb031d 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -342,7 +342,7 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess C# and Visual Basic References - C# and Visual Basic References + Referências do C# e do Visual Basic @@ -612,7 +612,7 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Desconstruir locais para "{0}" @@ -747,7 +747,7 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + "Localizar Todas as Referências" não invocado no símbolo aplicável @@ -2692,7 +2692,7 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas This {0} has {1} reference(s). - This {0} has {1} reference(s). + Este {0} tem {1} referência(s). @@ -3127,7 +3127,7 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas {0} reference - {0} reference + {0} referência @@ -3137,7 +3137,7 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas {0} references - {0} references + {0} referências @@ -3549,7 +3549,7 @@ O especificador de formato padrão "f" representa uma combinação de padrões d get-only property - get-only property + propriedade get-only diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index 746bd360349f8..fd75d8a154969 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -342,7 +342,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma C# and Visual Basic References - C# and Visual Basic References + Справочники по C# и Visual Basic @@ -612,7 +612,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + Деконструировать локальные объекты для "{0}" @@ -747,7 +747,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + Метод "Найти все ссылки" не вызван для применимого символа @@ -2692,7 +2692,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of This {0} has {1} reference(s). - This {0} has {1} reference(s). + Cсылок у {0}: {1}. @@ -3127,7 +3127,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} reference - {0} reference + Cсылок: {0} @@ -3137,7 +3137,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} references - {0} references + Ссылок: {0} @@ -3549,7 +3549,7 @@ The "f" standard format specifier represents a combination of the long date ("D" get-only property - get-only property + свойство, предназначенное только для получения diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 60853978f186f..a277621165a21 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -342,7 +342,7 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be C# and Visual Basic References - C# and Visual Basic References + C# ve Visual Basic Başvuruları @@ -612,7 +612,7 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + '{0}' için yerlileri yapısöküme uğratın @@ -747,7 +747,7 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + Uygulanabilir sembolde 'Tüm Referansları Bul' çağrılmadı @@ -2692,7 +2692,7 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri This {0} has {1} reference(s). - This {0} has {1} reference(s). + Bu {0}, {1} Başvuru içeriyor. @@ -3127,7 +3127,7 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri {0} reference - {0} reference + {0} başvuru @@ -3137,7 +3137,7 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri {0} references - {0} references + {0} başvuru @@ -3549,7 +3549,7 @@ The "f" standard format specifier represents a combination of the long date ("D" get-only property - get-only property + yalnızca alınabilen özellik diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index 99c527b473e8d..abf437cd09a74 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -342,7 +342,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma C# and Visual Basic References - C# and Visual Basic References + C# 和 Visual Basic 参考 @@ -612,7 +612,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + 解构“{0}”的局部变量 @@ -747,7 +747,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 未对适用的符号调用“查找所有引用” @@ -2692,7 +2692,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of This {0} has {1} reference(s). - This {0} has {1} reference(s). + 此 {0} 具有 {1} 个引用。 @@ -3127,7 +3127,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} reference - {0} reference + {0} 个引用 @@ -3137,7 +3137,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} references - {0} references + {0} 个引用 @@ -3549,7 +3549,7 @@ The "f" standard format specifier represents a combination of the long date ("D" get-only property - get-only property + get-only 属性 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 225bb9f4e8029..3aa02ddd7e74e 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -342,7 +342,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma C# and Visual Basic References - C# and Visual Basic References + C# 與 Visual Basic 參考 @@ -612,7 +612,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Deconstruct locals for '{0}' - Deconstruct locals for '{0}' + 解構 '{0}' 的區域 @@ -747,7 +747,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 'Find All References' not invoked on applicable symbol - 'Find All References' not invoked on applicable symbol + 未在適用的符號上叫用 [尋找所有參考] @@ -2692,7 +2692,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of This {0} has {1} reference(s). - This {0} has {1} reference(s). + 這個 {0} 有 {1} 個參考。 @@ -3127,7 +3127,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} reference - {0} reference + {0} 個參考 @@ -3137,7 +3137,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of {0} references - {0} references + {0} 個參考 @@ -3549,7 +3549,7 @@ The "f" standard format specifier represents a combination of the long date ("D" get-only property - get-only property + get-only 屬性 diff --git a/src/Features/LanguageServer/Protocol/Features/CodeFixes/CodeFixService.cs b/src/Features/LanguageServer/Protocol/Features/CodeFixes/CodeFixService.cs index e9c872bf6e7f9..579f4c7278c32 100644 --- a/src/Features/LanguageServer/Protocol/Features/CodeFixes/CodeFixService.cs +++ b/src/Features/LanguageServer/Protocol/Features/CodeFixes/CodeFixService.cs @@ -73,7 +73,7 @@ internal partial class CodeFixService : ICodeFixService private Func? GetShouldIncludeDiagnosticPredicate( TextDocument document, - CodeActionRequestPriority priority) + ICodeActionRequestPriorityProvider priorityProvider) { // For Normal or Low priority, we only need to execute analyzers which can report at least one fixable // diagnostic that can have a non-suppression/configuration fix. @@ -81,7 +81,7 @@ internal partial class CodeFixService : ICodeFixService // For CodeActionPriorityRequest.High, we only run compiler analyzer, which always has fixable diagnostics, // so we can return a null predicate here to include all diagnostics. - if (!(priority is CodeActionRequestPriority.Normal or CodeActionRequestPriority.Low)) + if (!(priorityProvider.Priority is CodeActionRequestPriority.Normal or CodeActionRequestPriority.Low)) return null; var hasWorkspaceFixers = TryGetWorkspaceFixersMap(document, out var workspaceFixersMap); @@ -97,11 +97,11 @@ internal partial class CodeFixService : ICodeFixService } public async Task GetMostSevereFixAsync( - TextDocument document, TextSpan range, CodeActionRequestPriority priority, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + TextDocument document, TextSpan range, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var (allDiagnostics, upToDate) = await _diagnosticService.TryGetDiagnosticsForSpanAsync( - document, range, GetShouldIncludeDiagnosticPredicate(document, priority), - includeSuppressedDiagnostics: false, priority, cancellationToken: cancellationToken).ConfigureAwait(false); + document, range, GetShouldIncludeDiagnosticPredicate(document, priorityProvider), + includeSuppressedDiagnostics: false, priorityProvider, cancellationToken: cancellationToken).ConfigureAwait(false); var buildOnlyDiagnosticsService = document.Project.Solution.Services.GetRequiredService(); allDiagnostics.AddRange(buildOnlyDiagnosticsService.GetBuildOnlyDiagnostics(document.Id)); @@ -144,7 +144,7 @@ internal partial class CodeFixService : ICodeFixService { await foreach (var collection in StreamFixesAsync( document, spanToDiagnostics, fixAllForInSpan: false, - priority, fallbackOptions, _ => null, cancellationToken).ConfigureAwait(false)) + priorityProvider, fallbackOptions, _ => null, cancellationToken).ConfigureAwait(false)) { // Stop at the result error we see. return collection; @@ -157,14 +157,14 @@ internal partial class CodeFixService : ICodeFixService public async IAsyncEnumerable StreamFixesAsync( TextDocument document, TextSpan range, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, Func addOperationScope, [EnumeratorCancellation] CancellationToken cancellationToken) { // We only need to compute suppression/configuration fixes when request priority is // 'CodeActionPriorityRequest.Lowest' or 'CodeActionPriorityRequest.None'. - var includeSuppressionFixes = priority is CodeActionRequestPriority.Lowest or CodeActionRequestPriority.None; + var includeSuppressionFixes = priorityProvider.Priority is CodeActionRequestPriority.Lowest or CodeActionRequestPriority.None; // REVIEW: this is the first and simplest design. basically, when ctrl+. is pressed, it asks diagnostic // service to give back current diagnostics for the given span, and it will use that to get fixes. @@ -177,8 +177,8 @@ internal partial class CodeFixService : ICodeFixService // We mark requests to GetDiagnosticsForSpanAsync as 'isExplicit = true' to indicate // user-invoked diagnostic requests, for example, user invoked Ctrl + Dot operation for lightbulb. var diagnostics = await _diagnosticService.GetDiagnosticsForSpanAsync( - document, range, GetShouldIncludeDiagnosticPredicate(document, priority), - includeCompilerDiagnostics: true, includeSuppressedDiagnostics: includeSuppressionFixes, priority: priority, + document, range, GetShouldIncludeDiagnosticPredicate(document, priorityProvider), + includeCompilerDiagnostics: true, includeSuppressedDiagnostics: includeSuppressionFixes, priorityProvider: priorityProvider, addOperationScope: addOperationScope, isExplicit: true, cancellationToken: cancellationToken).ConfigureAwait(false); var buildOnlyDiagnosticsService = document.Project.Solution.Services.GetRequiredService(); @@ -193,11 +193,11 @@ internal partial class CodeFixService : ICodeFixService var spanToDiagnostics = ConvertToMap(text, diagnostics); // 'CodeActionRequestPriority.Lowest' is used when the client only wants suppression/configuration fixes. - if (priority != CodeActionRequestPriority.Lowest) + if (priorityProvider.Priority != CodeActionRequestPriority.Lowest) { await foreach (var collection in StreamFixesAsync( document, spanToDiagnostics, fixAllForInSpan: false, - priority, fallbackOptions, addOperationScope, cancellationToken).ConfigureAwait(false)) + priorityProvider, fallbackOptions, addOperationScope, cancellationToken).ConfigureAwait(false)) { yield return collection; } @@ -271,7 +271,7 @@ internal partial class CodeFixService : ICodeFixService }; await foreach (var collection in StreamFixesAsync( - document, spanToDiagnostics, fixAllForInSpan: true, CodeActionRequestPriority.None, + document, spanToDiagnostics, fixAllForInSpan: true, new DefaultCodeActionRequestPriorityProvider(), fallbackOptions, addOperationScope: static _ => null, cancellationToken).ConfigureAwait(false)) { if (collection.FixAllState is not null && collection.SupportedScopes.Contains(FixAllScope.Document)) @@ -401,7 +401,7 @@ private bool TryGetWorkspaceFixersPriorityMap(TextDocument document, [NotNullWhe TextDocument document, SortedDictionary> spanToDiagnostics, bool fixAllForInSpan, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, Func addOperationScope, [EnumeratorCancellation] CancellationToken cancellationToken) @@ -476,7 +476,7 @@ private bool TryGetWorkspaceFixersPriorityMap(TextDocument document, [NotNullWhe { cancellationToken.ThrowIfCancellationRequested(); - if (priority != CodeActionRequestPriority.None && priority != fixer.RequestPriority) + if (!priorityProvider.MatchesPriority(fixer)) continue; foreach (var (span, diagnostics) in fixerToRangesAndDiagnostics[fixer]) diff --git a/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs b/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs index 46e1536845741..b595aefd21d5a 100644 --- a/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs +++ b/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs @@ -16,14 +16,14 @@ namespace Microsoft.CodeAnalysis.CodeFixes { internal interface ICodeFixService { - IAsyncEnumerable StreamFixesAsync(TextDocument document, TextSpan textSpan, CodeActionRequestPriority priority, CodeActionOptionsProvider options, Func addOperationScope, CancellationToken cancellationToken); + IAsyncEnumerable StreamFixesAsync(TextDocument document, TextSpan textSpan, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider options, Func addOperationScope, CancellationToken cancellationToken); /// /// Similar to except that instead of streaming all results, this ends with the /// first. This will also attempt to return a fix for an error first, but will fall back to any fix if that /// does not succeed. /// - Task GetMostSevereFixAsync(TextDocument document, TextSpan range, CodeActionRequestPriority priority, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken); + Task GetMostSevereFixAsync(TextDocument document, TextSpan range, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken); Task GetDocumentFixAllForIdInSpanAsync(TextDocument document, TextSpan textSpan, string diagnosticId, DiagnosticSeverity severity, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken); Task ApplyCodeFixesForSpecificDiagnosticIdAsync(TDocument document, string diagnosticId, DiagnosticSeverity severity, IProgressTracker progressTracker, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) @@ -34,13 +34,13 @@ Task ApplyCodeFixesForSpecificDiagnosticIdAsync(TDocument internal static class ICodeFixServiceExtensions { public static IAsyncEnumerable StreamFixesAsync(this ICodeFixService service, TextDocument document, TextSpan range, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) - => service.StreamFixesAsync(document, range, CodeActionRequestPriority.None, fallbackOptions, addOperationScope: _ => null, cancellationToken); + => service.StreamFixesAsync(document, range, new DefaultCodeActionRequestPriorityProvider(), fallbackOptions, addOperationScope: _ => null, cancellationToken); public static Task> GetFixesAsync(this ICodeFixService service, TextDocument document, TextSpan range, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) => service.StreamFixesAsync(document, range, fallbackOptions, cancellationToken).ToImmutableArrayAsync(cancellationToken); - public static Task> GetFixesAsync(this ICodeFixService service, TextDocument document, TextSpan textSpan, CodeActionRequestPriority priority, CodeActionOptionsProvider fallbackOptions, Func addOperationScope, CancellationToken cancellationToken) - => service.StreamFixesAsync(document, textSpan, priority, fallbackOptions, addOperationScope, cancellationToken).ToImmutableArrayAsync(cancellationToken); + public static Task> GetFixesAsync(this ICodeFixService service, TextDocument document, TextSpan textSpan, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, Func addOperationScope, CancellationToken cancellationToken) + => service.StreamFixesAsync(document, textSpan, priorityProvider, fallbackOptions, addOperationScope, cancellationToken).ToImmutableArrayAsync(cancellationToken); public static Task GetDocumentFixAllForIdInSpanAsync(this ICodeFixService service, TextDocument document, TextSpan range, string diagnosticId, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) => service.GetDocumentFixAllForIdInSpanAsync(document, range, diagnosticId, DiagnosticSeverity.Hidden, fallbackOptions, cancellationToken); diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService.cs index ec43ed93eb37b..52a6b4df06d6f 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService.cs @@ -73,7 +73,7 @@ public void Reanalyze(Workspace workspace, IEnumerable? projectIds = TextSpan range, Func? shouldIncludeDiagnostic, bool includeSuppressedDiagnostics = false, - CodeActionRequestPriority priority = CodeActionRequestPriority.None, + ICodeActionRequestPriorityProvider? priorityProvider = null, DiagnosticKind diagnosticKinds = DiagnosticKind.All, bool isExplicit = false, CancellationToken cancellationToken = default) @@ -83,10 +83,12 @@ public void Reanalyze(Workspace workspace, IEnumerable? projectIds = // always make sure that analyzer is called on background thread. return Task.Run(async () => { + priorityProvider ??= new DefaultCodeActionRequestPriorityProvider(); + using var _ = ArrayBuilder.GetInstance(out var diagnostics); var upToDate = await analyzer.TryAppendDiagnosticsForSpanAsync( document, range, diagnostics, shouldIncludeDiagnostic, - includeSuppressedDiagnostics, true, priority, blockForData: false, + includeSuppressedDiagnostics, true, priorityProvider, blockForData: false, addOperationScope: null, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false); return (diagnostics.ToImmutable(), upToDate); }, cancellationToken); @@ -101,7 +103,7 @@ public void Reanalyze(Workspace workspace, IEnumerable? projectIds = Func? shouldIncludeDiagnostic, bool includeCompilerDiagnostics, bool includeSuppressedDiagnostics, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider? priorityProvider, Func? addOperationScope, DiagnosticKind diagnosticKinds, bool isExplicit, @@ -109,10 +111,12 @@ public void Reanalyze(Workspace workspace, IEnumerable? projectIds = { if (_map.TryGetValue(document.Project.Solution.Workspace, out var analyzer)) { + priorityProvider ??= new DefaultCodeActionRequestPriorityProvider(); + // always make sure that analyzer is called on background thread. return Task.Run(() => analyzer.GetDiagnosticsForSpanAsync( document, range, shouldIncludeDiagnostic, includeSuppressedDiagnostics, includeCompilerDiagnostics, - priority, blockForData: true, addOperationScope, diagnosticKinds, isExplicit, cancellationToken), cancellationToken); + priorityProvider, blockForData: true, addOperationScope, diagnosticKinds, isExplicit, cancellationToken), cancellationToken); } return SpecializedTasks.EmptyImmutableArray(); diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.ActiveFileState.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.ActiveFileState.cs index 0f0c1c9798fd5..80b3249e48739 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.ActiveFileState.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.ActiveFileState.cs @@ -42,8 +42,8 @@ public void ResetVersion() lock (_gate) { // reset version of cached data so that we can recalculate new data (ex, OnDocumentReset) - _syntax = new DocumentAnalysisData(VersionStamp.Default, _syntax.Items); - _semantic = new DocumentAnalysisData(VersionStamp.Default, _semantic.Items); + _syntax = new DocumentAnalysisData(VersionStamp.Default, _syntax.LineCount, _syntax.Items); + _semantic = new DocumentAnalysisData(VersionStamp.Default, _semantic.LineCount, _semantic.Items); } } diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.AnalysisData.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.AnalysisData.cs index e72d4e5ade939..8814eae9d0f6d 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.AnalysisData.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.AnalysisData.cs @@ -20,13 +20,18 @@ internal partial class DiagnosticIncrementalAnalyzer /// private readonly struct DocumentAnalysisData { - public static readonly DocumentAnalysisData Empty = new(VersionStamp.Default, ImmutableArray.Empty); + public static readonly DocumentAnalysisData Empty = new(VersionStamp.Default, lineCount: 0, ImmutableArray.Empty); /// /// Version of the diagnostic data. /// public readonly VersionStamp Version; + /// + /// Number of lines in the document. + /// + public readonly int LineCount; + /// /// Current data that matches the version. /// @@ -37,24 +42,25 @@ internal partial class DiagnosticIncrementalAnalyzer /// public readonly ImmutableArray OldItems; - public DocumentAnalysisData(VersionStamp version, ImmutableArray items) + public DocumentAnalysisData(VersionStamp version, int lineCount, ImmutableArray items) { Debug.Assert(!items.IsDefault); Version = version; + LineCount = lineCount; Items = items; OldItems = default; } - public DocumentAnalysisData(VersionStamp version, ImmutableArray oldItems, ImmutableArray newItems) - : this(version, newItems) + public DocumentAnalysisData(VersionStamp version, int lineCount, ImmutableArray oldItems, ImmutableArray newItems) + : this(version, lineCount, newItems) { Debug.Assert(!oldItems.IsDefault); OldItems = oldItems; } public DocumentAnalysisData ToPersistData() - => new(Version, Items); + => new(Version, LineCount, Items); public bool FromCache { diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs index 8b3b95dd9c6e5..28794cc60a74c 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs @@ -152,9 +152,10 @@ internal partial class DiagnosticIncrementalAnalyzer var version = await GetDiagnosticVersionAsync(document.Project, cancellationToken).ConfigureAwait(false); var state = stateSet.GetOrCreateActiveFileState(document.Id); var existingData = state.GetAnalysisData(kind); + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); // we only care about local diagnostics - return new DocumentAnalysisData(version, existingData.Items, diagnostics.ToImmutableArrayOrEmpty()); + return new DocumentAnalysisData(version, text.Lines.Count, existingData.Items, diagnostics.ToImmutableArrayOrEmpty()); } catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) { diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.ProjectStates.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.ProjectStates.cs index 5d439d49fc467..8e2f1080ff50e 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.ProjectStates.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.ProjectStates.cs @@ -54,7 +54,7 @@ public IEnumerable GetAllProjectStateSets() { // check if the analyzer references have changed since the last time we updated the map: if (_projectAnalyzerStateMap.TryGetValue(project.Id, out var entry) && - entry.AnalyzerReferences.Equals(project.AnalyzerReferences)) + entry.AnalyzerReferences.SequenceEqual(project.AnalyzerReferences)) { return entry; } diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateSet.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateSet.cs index f565959af0d30..480e3b6a5cc33 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateSet.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateSet.cs @@ -129,12 +129,13 @@ public async Task OnDocumentOpenedAsync(TextDocument document) } var result = await projectState.GetAnalysisDataAsync(document, avoidLoadingData: false, CancellationToken.None).ConfigureAwait(false); + var text = await document.GetTextAsync(CancellationToken.None).ConfigureAwait(false); // store analysis result to active file state: var activeFileState = GetOrCreateActiveFileState(document.Id); - activeFileState.Save(AnalysisKind.Syntax, new DocumentAnalysisData(result.Version, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Syntax))); - activeFileState.Save(AnalysisKind.Semantic, new DocumentAnalysisData(result.Version, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Semantic))); + activeFileState.Save(AnalysisKind.Syntax, new DocumentAnalysisData(result.Version, text.Lines.Count, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Syntax))); + activeFileState.Save(AnalysisKind.Semantic, new DocumentAnalysisData(result.Version, text.Lines.Count, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Semantic))); return true; } diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs index 3c04d4469c10f..90436c2447fca 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs @@ -24,12 +24,12 @@ internal partial class DiagnosticIncrementalAnalyzer { public async Task TryAppendDiagnosticsForSpanAsync( TextDocument document, TextSpan? range, ArrayBuilder result, Func? shouldIncludeDiagnostic, - bool includeSuppressedDiagnostics, bool includeCompilerDiagnostics, CodeActionRequestPriority priority, bool blockForData, + bool includeSuppressedDiagnostics, bool includeCompilerDiagnostics, ICodeActionRequestPriorityProvider priorityProvider, bool blockForData, Func? addOperationScope, DiagnosticKind diagnosticKinds, bool isExplicit, CancellationToken cancellationToken) { var getter = await LatestDiagnosticsForSpanGetter.CreateAsync( this, document, range, blockForData, addOperationScope, includeSuppressedDiagnostics, includeCompilerDiagnostics, - priority, shouldIncludeDiagnostic, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false); + priorityProvider, shouldIncludeDiagnostic, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false); return await getter.TryGetAsync(result, cancellationToken).ConfigureAwait(false); } @@ -39,7 +39,7 @@ internal partial class DiagnosticIncrementalAnalyzer Func? shouldIncludeDiagnostic, bool includeSuppressedDiagnostics, bool includeCompilerDiagnostics, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, bool blockForData, Func? addOperationScope, DiagnosticKind diagnosticKinds, @@ -49,7 +49,7 @@ internal partial class DiagnosticIncrementalAnalyzer using var _ = ArrayBuilder.GetInstance(out var list); var result = await TryAppendDiagnosticsForSpanAsync( document, range, list, shouldIncludeDiagnostic, includeSuppressedDiagnostics, includeCompilerDiagnostics, - priority, blockForData, addOperationScope, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false); + priorityProvider, blockForData, addOperationScope, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false); Debug.Assert(result); return list.ToImmutable(); } @@ -74,7 +74,7 @@ private sealed class LatestDiagnosticsForSpanGetter private readonly TextSpan? _range; private readonly bool _blockForData; private readonly bool _includeSuppressedDiagnostics; - private readonly CodeActionRequestPriority _priority; + private readonly ICodeActionRequestPriorityProvider _priorityProvider; private readonly Func? _shouldIncludeDiagnostic; private readonly bool _includeCompilerDiagnostics; private readonly Func? _addOperationScope; @@ -94,7 +94,7 @@ private sealed class LatestDiagnosticsForSpanGetter Func? addOperationScope, bool includeSuppressedDiagnostics, bool includeCompilerDiagnostics, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, Func? shouldIncludeDiagnostic, DiagnosticKind diagnosticKinds, bool isExplicit, @@ -112,11 +112,14 @@ private sealed class LatestDiagnosticsForSpanGetter // updating the error list simultaneously. var cacheFullDocumentDiagnostics = owner.AnalyzerService.GlobalOptions.IsLspPullDiagnostics(); + // Note that some callers, such as diagnostic tagger, might pass in a range equal to the entire document span. + // We clear out range for such cases as we are computing full document diagnostics. + if (range == new TextSpan(0, text.Length)) + range = null; + // We log performance info when we are computing diagnostics for a span // and also blocking for data, i.e. for lightbulb code path for "Ctrl + Dot" user command. - // Note that some callers, such as diagnostic tagger, might pass in a range equal to the entire document span, - // so we also check that the range length is lesser then the document text length. - var logPerformanceInfo = range.HasValue && blockForData && range.Value.Length < text.Length; + var logPerformanceInfo = range.HasValue && blockForData; var compilationWithAnalyzers = await GetOrCreateCompilationWithAnalyzersAsync(document.Project, ideOptions, stateSets, includeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); // If we are computing full document diagnostics, we will attempt to perform incremental @@ -128,7 +131,7 @@ private sealed class LatestDiagnosticsForSpanGetter return new LatestDiagnosticsForSpanGetter( owner, compilationWithAnalyzers, document, text, stateSets, shouldIncludeDiagnostic, includeCompilerDiagnostics, - range, blockForData, addOperationScope, includeSuppressedDiagnostics, priority, cacheFullDocumentDiagnostics, + range, blockForData, addOperationScope, includeSuppressedDiagnostics, priorityProvider, cacheFullDocumentDiagnostics, isExplicit, logPerformanceInfo, incrementalAnalysis, diagnosticKinds); } @@ -170,7 +173,7 @@ private sealed class LatestDiagnosticsForSpanGetter bool blockForData, Func? addOperationScope, bool includeSuppressedDiagnostics, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, bool cacheFullDocumentDiagnostics, bool isExplicit, bool logPerformanceInfo, @@ -188,7 +191,7 @@ private sealed class LatestDiagnosticsForSpanGetter _blockForData = blockForData; _addOperationScope = addOperationScope; _includeSuppressedDiagnostics = includeSuppressedDiagnostics; - _priority = priority; + _priorityProvider = priorityProvider; _cacheFullDocumentDiagnostics = cacheFullDocumentDiagnostics; _isExplicit = isExplicit; _logPerformanceInfo = logPerformanceInfo; @@ -203,15 +206,15 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat var containsFullResult = true; // Try to get cached diagnostics, and also compute non-cached state sets that need diagnostic computation. - using var _1 = ArrayBuilder.GetInstance(out var syntaxAnalyzers); + using var _1 = ArrayBuilder<(StateSet stateSet, DocumentAnalysisData? existingData)>.GetInstance(out var syntaxAnalyzers); // If we are performing incremental member edit analysis to compute diagnostics incrementally, // we divide the analyzers into those that support span-based incremental analysis and // those that do not support incremental analysis and must be executed for the entire document. // Otherwise, if we are not performing incremental analysis, all semantic analyzers are added // to the span-based analyzer set as we want to compute diagnostics only for the given span. - using var _2 = ArrayBuilder.GetInstance(out var semanticSpanBasedAnalyzers); - using var _3 = ArrayBuilder.GetInstance(out var semanticDocumentBasedAnalyzers); + using var _2 = ArrayBuilder<(StateSet stateSet, DocumentAnalysisData? existingData)>.GetInstance(out var semanticSpanBasedAnalyzers); + using var _3 = ArrayBuilder<(StateSet stateSet, DocumentAnalysisData? existingData)>.GetInstance(out var semanticDocumentBasedAnalyzers); foreach (var stateSet in _stateSets) { @@ -231,22 +234,28 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat : _diagnosticKind == DiagnosticKind.AnalyzerSemantic; } - if (includeSyntax && !await TryAddCachedDocumentDiagnosticsAsync(stateSet, AnalysisKind.Syntax, list, cancellationToken).ConfigureAwait(false)) - syntaxAnalyzers.Add(stateSet); + if (includeSyntax) + { + var (added, existingData) = await TryAddCachedDocumentDiagnosticsAsync(stateSet, AnalysisKind.Syntax, list, cancellationToken).ConfigureAwait(false); + if (!added) + syntaxAnalyzers.Add((stateSet, existingData)); + } - if (includeSemantic && - _document is Document && - !await TryAddCachedDocumentDiagnosticsAsync(stateSet, AnalysisKind.Semantic, list, cancellationToken).ConfigureAwait(false)) + if (includeSemantic && _document is Document) { - if (ShouldRunSemanticAnalysis(stateSet.Analyzer, _incrementalAnalysis, _blockForData, - semanticSpanBasedAnalyzers, semanticDocumentBasedAnalyzers, out var stateSets)) + var (added, existingData) = await TryAddCachedDocumentDiagnosticsAsync(stateSet, AnalysisKind.Semantic, list, cancellationToken).ConfigureAwait(false); + if (!added) { - stateSets.Add(stateSet); - } - else - { - Debug.Assert(!_blockForData); - containsFullResult = false; + if (ShouldRunSemanticAnalysis(stateSet.Analyzer, _incrementalAnalysis, _blockForData, + semanticSpanBasedAnalyzers, semanticDocumentBasedAnalyzers, out var stateSets)) + { + stateSets.Add((stateSet, existingData)); + } + else + { + Debug.Assert(!_blockForData); + containsFullResult = false; + } } } } @@ -293,9 +302,9 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat DiagnosticAnalyzer analyzer, bool incrementalAnalysis, bool blockForData, - ArrayBuilder semanticSpanBasedAnalyzers, - ArrayBuilder semanticDocumentBasedAnalyzers, - [NotNullWhen(true)] out ArrayBuilder? selectedStateSets) + ArrayBuilder<(StateSet stateSet, DocumentAnalysisData? existingData)> semanticSpanBasedAnalyzers, + ArrayBuilder<(StateSet stateSet, DocumentAnalysisData? existingData)> semanticDocumentBasedAnalyzers, + [NotNullWhen(true)] out ArrayBuilder<(StateSet stateSet, DocumentAnalysisData? existingData)>? selectedStateSets) { // If the caller doesn't want us to force compute diagnostics, // we don't run semantic analysis. @@ -325,21 +334,24 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat } /// - /// Returns if we were able to add the cached diagnostics and we do not need to compute them fresh. + /// Returns a tuple with following fields: + /// 1. 'added': if we were able to add the cached diagnostics and we do not need to compute them fresh. + /// 2. 'existingData': Currently cached for the document being analyzed. + /// Note that this cached data may be from a prior document snapshot. /// - private async Task TryAddCachedDocumentDiagnosticsAsync( + private async Task<(bool added, DocumentAnalysisData? existingData)> TryAddCachedDocumentDiagnosticsAsync( StateSet stateSet, AnalysisKind kind, ArrayBuilder list, CancellationToken cancellationToken) { if (!stateSet.Analyzer.SupportAnalysisKind(kind) || - !MatchesPriority(stateSet.Analyzer)) + !_priorityProvider.MatchesPriority(stateSet.Analyzer)) { // In the case where the analyzer doesn't support the requested kind or priority, act as if we succeeded, but just // added no items to the result. Effectively we did add the cached values, just that all the values that could have // been added have been filtered out. We do not want to then compute the up to date values in the caller. - return true; + return (true, null); } // make sure we get state even when none of our analyzer has ran yet. @@ -357,14 +369,14 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat list.Add(item); } - return true; + return (true, existingData); } - return false; + return (false, existingData); } private async Task ComputeDocumentDiagnosticsAsync( - ImmutableArray stateSets, + ImmutableArray<(StateSet stateSet, DocumentAnalysisData? existingData)> stateSetsAndExistingData, AnalysisKind kind, TextSpan? span, ArrayBuilder builder, @@ -372,9 +384,28 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat CancellationToken cancellationToken) { Debug.Assert(!incrementalAnalysis || kind == AnalysisKind.Semantic); - Debug.Assert(!incrementalAnalysis || stateSets.All(stateSet => stateSet.Analyzer.SupportsSpanBasedSemanticDiagnosticAnalysis())); + Debug.Assert(!incrementalAnalysis || stateSetsAndExistingData.All(stateSetAndData => stateSetAndData.stateSet.Analyzer.SupportsSpanBasedSemanticDiagnosticAnalysis())); + + using var _ = ArrayBuilder.GetInstance(stateSetsAndExistingData.Length, out var stateSetBuilder); + foreach (var (stateSet, existingData) in stateSetsAndExistingData) + { + var analyzer = stateSet.Analyzer; + if (_priorityProvider.MatchesPriority(analyzer)) + { + // Check if this is an expensive analyzer that needs to be de-prioritized to a lower priority bucket. + // If so, we skip this analyzer from execution in the current priority bucket. + // We will subsequently execute this analyzer in the lower priority bucket. + Contract.ThrowIfNull(existingData); + if (await TryDeprioritizeAnalyzerAsync(analyzer, existingData.Value).ConfigureAwait(false)) + { + continue; + } + + stateSetBuilder.Add(stateSet); + } + } - stateSets = stateSets.WhereAsArray(s => MatchesPriority(s.Analyzer)); + var stateSets = stateSetBuilder.ToImmutable(); if (stateSets.IsEmpty) return; @@ -409,13 +440,102 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat if (_cacheFullDocumentDiagnostics && !span.HasValue) { var state = stateSet.GetOrCreateActiveFileState(_document.Id); - var data = new DocumentAnalysisData(version, diagnostics); + var data = new DocumentAnalysisData(version, _text.Lines.Count, diagnostics); state.Save(executor.AnalysisScope.Kind, data); } } if (incrementalAnalysis) _owner._incrementalMemberEditAnalyzer.UpdateDocumentWithCachedDiagnostics((Document)_document); + + async Task TryDeprioritizeAnalyzerAsync(DiagnosticAnalyzer analyzer, DocumentAnalysisData existingData) + { + // PERF: In order to improve lightbulb performance, we perform de-prioritization optimization for certain analyzers + // that moves the analyzer to a lower priority bucket. However, to ensure that de-prioritization happens for very rare cases, + // we only perform this optimizations when following conditions are met: + // 1. We are performing semantic span-based analysis. + // 2. We are processing 'CodeActionRequestPriority.Normal' priority request. + // 3. Analyzer registers certain actions that are known to lead to high performance impact due to its broad analysis scope, + // such as SymbolStart/End actions and SemanticModel actions. + // 4. Analyzer did not report a diagnostic on the same line in prior document snapshot. + + // Conditions 1. and 2. + if (kind != AnalysisKind.Semantic || + !span.HasValue || + _priorityProvider.Priority != CodeActionRequestPriority.Normal) + { + return false; + } + + Debug.Assert(span.Value.Length < _text.Length); + + // Condition 3. + // Check if this is a candidate analyzer that can be de-prioritized into a lower priority bucket based on registered actions. + if (!await IsCandidateForDeprioritizationBasedOnRegisteredActionsAsync(analyzer).ConfigureAwait(false)) + { + return false; + } + + // Condition 4. + // We do not want to de-prioritize this analyzer if it reported a diagnostic on a prior document snapshot, + // such that diagnostic's start/end lines intersect the current analysis span's start/end lines. + // If an analyzer reported such a diagnostic, it is highly likely that the user intends to invoke the code fix + // for this diagnostic. Additionally, it is also highly likely that this analyzer will report a diagnostic + // on the current snapshot. So, we deem this as an important analyzer that should not be de-prioritized here. + // Note that we only perform this analysis if the prior document, whose existingData is cached, had same number + // of source lines as the current document snapshot. Otherwise, the start/end lines comparison across + // snapshots is not meaningful. + if (existingData.LineCount == _text.Lines.Count && + !existingData.Items.IsEmpty) + { + _text.GetLinesAndOffsets(span.Value, out var startLineNumber, out var _, out var endLineNumber, out var _); + + foreach (var diagnostic in existingData.Items) + { + if (diagnostic.DataLocation.UnmappedFileSpan.StartLinePosition.Line <= endLineNumber && + diagnostic.DataLocation.UnmappedFileSpan.EndLinePosition.Line >= startLineNumber) + { + return false; + } + } + } + + // 'LightbulbSkipExecutingDeprioritizedAnalyzers' option determines if we want to execute this analyzer + // in low priority bucket or skip it completely. If the option is not set, track the de-prioritized + // analyzer to be executed in low priority bucket. + // Note that 'AddDeprioritizedAnalyzerWithLowPriority' call below mutates the state in the provider to + // track this analyzer. This ensures that when the owner of this provider calls us back to execute + // the low priority bucket, we can still get back to this analyzer and execute it that time. + if (!_owner.GlobalOptions.GetOption(DiagnosticOptionsStorage.LightbulbSkipExecutingDeprioritizedAnalyzers)) + _priorityProvider.AddDeprioritizedAnalyzerWithLowPriority(analyzer); + + return true; + } + + // Returns true if this is an analyzer that is a candidate to be de-prioritized to + // 'CodeActionRequestPriority.Low' priority for improvement in analyzer + // execution performance for priority buckets above 'Low' priority. + // Based on performance measurements, currently only analyzers which register SymbolStart/End actions + // or SemanticModel actions are considered candidates to be de-prioritized. However, these semantics + // could be changed in future based on performance measurements. + async Task IsCandidateForDeprioritizationBasedOnRegisteredActionsAsync(DiagnosticAnalyzer analyzer) + { + // We deprioritize SymbolStart/End and SemanticModel analyzers from 'Normal' to 'Low' priority bucket, + // as these are computationally more expensive. + // Note that we never de-prioritize compiler analyzer, even though it registers a SemanticModel action. + if (_compilationWithAnalyzers == null || + analyzer.IsWorkspaceDiagnosticAnalyzer() || + analyzer.IsCompilerAnalyzer()) + { + return false; + } + + var telemetryInfo = await _compilationWithAnalyzers.GetAnalyzerTelemetryInfoAsync(analyzer, cancellationToken).ConfigureAwait(false); + if (telemetryInfo == null) + return false; + + return telemetryInfo.SymbolStartActionsCount > 0 || telemetryInfo.SemanticModelActionsCount > 0; + } } private async Task>> ComputeDocumentDiagnosticsCoreAsync( @@ -450,28 +570,6 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat } } - private bool MatchesPriority(DiagnosticAnalyzer analyzer) - { - // If caller isn't asking for prioritized result, then run all analyzers. - if (_priority == CodeActionRequestPriority.None) - return true; - - // 'CodeActionRequestPriority.Lowest' is used for suppression/configuration fixes, - // which requires all analyzer diagnostics. - if (_priority == CodeActionRequestPriority.Lowest) - return true; - - // The compiler analyzer always counts for any priority. It's diagnostics may be fixed - // by high pri or normal pri fixers. - if (analyzer.IsCompilerAnalyzer()) - return true; - - var analyzerPriority = analyzer is IBuiltInAnalyzer { RequestPriority: var requestPriority } - ? requestPriority - : CodeActionRequestPriority.Normal; - return _priority == analyzerPriority; - } - private bool ShouldInclude(DiagnosticData diagnostic) { return diagnostic.DocumentId == _document.Id && diff --git a/src/Features/LanguageServer/Protocol/Features/Options/DiagnosticOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/DiagnosticOptionsStorage.cs index a28769f153e76..1c10675c682aa 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/DiagnosticOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/DiagnosticOptionsStorage.cs @@ -13,5 +13,8 @@ internal sealed class DiagnosticOptionsStorage public static readonly Option2 LogTelemetryForBackgroundAnalyzerExecution = new( "dotnet_log_telemetry_for_background_analyzer_execution", defaultValue: false); + + public static readonly Option2 LightbulbSkipExecutingDeprioritizedAnalyzers = new( + "dotnet_lightbulb_skip_executing_deprioritized_analyzers", defaultValue: false); } } diff --git a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs index a98bf2d97bca2..14c1f2367d754 100644 --- a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs +++ b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs @@ -36,7 +36,7 @@ internal class UnifiedSuggestedActionsSource ICodeFixService codeFixService, TextDocument document, TextSpan selection, - CodeActionRequestPriority priority, + ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, Func addOperationScope, CancellationToken cancellationToken) @@ -48,7 +48,7 @@ internal class UnifiedSuggestedActionsSource var fixes = await Task.Run(() => codeFixService.GetFixesAsync( document, selection, - priority, + priorityProvider, fallbackOptions, addOperationScope, cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs index 978c001b9898d..067c35c239231 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs @@ -242,7 +242,7 @@ private static CodeAction GetNestedActionsFromActionSet(IUnifiedSuggestedAction var codeFixes = await UnifiedSuggestedActionsSource.GetFilterAndOrderCodeFixesAsync( document.Project.Solution.Workspace, codeFixService, document, textSpan, - CodeActionRequestPriority.None, + new DefaultCodeActionRequestPriorityProvider(), fallbackOptions, addOperationScope: _ => null, cancellationToken).ConfigureAwait(false); var codeRefactorings = await UnifiedSuggestedActionsSource.GetFilterAndOrderCodeRefactoringsAsync( diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs index a0b3d4e8002e3..230a46d611f2d 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs @@ -75,7 +75,6 @@ static SemanticTokensHelpers() Dictionary tokenTypesToIndex, LSP.Range? range, ClassificationOptions options, - bool includeSyntacticClassifications, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); @@ -86,7 +85,7 @@ static SemanticTokensHelpers() var textSpan = range is null ? root.FullSpan : ProtocolConversions.RangeToTextSpan(range, text); var classifiedSpans = await GetClassifiedSpansForDocumentAsync( - document, textSpan, options, includeSyntacticClassifications, cancellationToken).ConfigureAwait(false); + document, textSpan, options, cancellationToken).ConfigureAwait(false); // Multi-line tokens are not supported by VS (tracked by https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1265495). // Roslyn's classifier however can return multi-line classified spans, so we must break these up into single-line spans. @@ -101,41 +100,24 @@ static SemanticTokensHelpers() Document document, TextSpan textSpan, ClassificationOptions options, - bool includeSyntacticClassifications, CancellationToken cancellationToken) { var classificationService = document.GetRequiredLanguageService(); using var _ = ArrayBuilder.GetInstance(out var classifiedSpans); - // Case 1 - Generated Razor documents: - // In Razor, the C# syntax classifier does not run on the client. This means we need to return both - // syntactic and semantic classifications. - // Case 2 - C# and VB documents: - // In C#/VB, the syntax classifier runs on the client. This means we only need to return semantic - // classifications. - // - // Ideally, Razor will eventually run the classifier on their end so we can get rid of this special - // casing: https://github.com/dotnet/razor-tooling/issues/5850 - if (includeSyntacticClassifications) - { - // `includeAdditiveSpans` will add token modifiers such as 'static', which we want to include in LSP. - var spans = await ClassifierHelper.GetClassifiedSpansAsync( - document, textSpan, options, includeAdditiveSpans: true, cancellationToken).ConfigureAwait(false); - - // The spans returned to us may include some empty spans, which we don't care about. We also don't care - // about the 'text' classification. It's added for everything between real classifications (including - // whitespace), and just means 'don't classify this'. No need for us to actually include that in - // semantic tokens as it just wastes space in the result. - var nonEmptySpans = spans.Where(s => !s.TextSpan.IsEmpty && s.ClassificationType != ClassificationTypeNames.Text); - classifiedSpans.AddRange(nonEmptySpans); - } - else - { - await classificationService.AddSemanticClassificationsAsync( - document, textSpan, options, classifiedSpans, cancellationToken).ConfigureAwait(false); - await classificationService.AddEmbeddedLanguageClassificationsAsync( - document, textSpan, options, classifiedSpans, cancellationToken).ConfigureAwait(false); - } + // We always return both syntactic and semantic classifications. If there is a syntactic classifier running on the client + // then the semantic token classifications will override them. + + // `includeAdditiveSpans` will add token modifiers such as 'static', which we want to include in LSP. + var spans = await ClassifierHelper.GetClassifiedSpansAsync( + document, textSpan, options, includeAdditiveSpans: true, cancellationToken).ConfigureAwait(false); + + // The spans returned to us may include some empty spans, which we don't care about. We also don't care + // about the 'text' classification. It's added for everything between real classifications (including + // whitespace), and just means 'don't classify this'. No need for us to actually include that in + // semantic tokens as it just wastes space in the result. + var nonEmptySpans = spans.Where(s => !s.TextSpan.IsEmpty && s.ClassificationType != ClassificationTypeNames.Text); + classifiedSpans.AddRange(nonEmptySpans); // Classified spans are not guaranteed to be returned in a certain order so we sort them to be safe. classifiedSpans.Sort(ClassifiedSpanComparer.Instance); diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs index 0f50523e03e6c..481335a21e58e 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs @@ -60,7 +60,6 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(LSP.SemanticTokensRangeP SemanticTokensHelpers.TokenTypeToIndex, request.Range, options, - includeSyntacticClassifications: contextDocument.IsRazorDocument(), cancellationToken).ConfigureAwait(false); // The above call to get semantic tokens may be inaccurate (because we use frozen partial semantics). Kick diff --git a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs index 9820ca9245ce2..8d03d12bf3236 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs @@ -38,32 +38,6 @@ static class C { } var range = new LSP.Range { Start = new Position(0, 0), End = new Position(2, 0) }; var results = await RunGetSemanticTokensRangeAsync(testLspServer, testLspServer.GetLocations("caret").First(), range); - // Everything is colorized syntactically, so we shouldn't be returning any semantic results. - var expectedResults = new LSP.SemanticTokens - { - Data = Array.Empty() - }; - - Assert.Equal(expectedResults.Data, results.Data); - } - - [Theory, CombinatorialData] - public async Task TestGetSemanticTokensRange_FullDoc_RazorAsync(bool mutatingLspWorkspace) - { - // Razor docs should be returning semantic + syntactic reuslts. - var markup = -@"{|caret:|}// Comment -static class C { } -"; - await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace); - - var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); - var range = new LSP.Range { Start = new Position(0, 0), End = new Position(2, 0) }; - var options = ClassificationOptions.Default; - - var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( - document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); - var expectedResults = new LSP.SemanticTokens { Data = new int[] @@ -78,12 +52,12 @@ static class C { } }, }; - await VerifyBasicInvariantsAndNoMultiLineTokens(testLspServer, results).ConfigureAwait(false); - AssertEx.Equal(ConvertToReadableFormat(expectedResults.Data), ConvertToReadableFormat(results)); + await VerifyBasicInvariantsAndNoMultiLineTokens(testLspServer, results.Data).ConfigureAwait(false); + AssertEx.Equal(ConvertToReadableFormat(expectedResults.Data), ConvertToReadableFormat(results.Data)); } [Theory, CombinatorialData] - public async Task TestGetSemanticTokensRange_PartialDoc_RazorAsync(bool mutatingLspWorkspace) + public async Task TestGetSemanticTokensRange_PartialDocAsync(bool mutatingLspWorkspace) { // Razor docs should be returning semantic + syntactic reuslts. var markup = @@ -96,7 +70,7 @@ static class C { } var range = new LSP.Range { Start = new Position(1, 0), End = new Position(2, 0) }; var options = ClassificationOptions.Default; var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( - document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); + document, SemanticTokensHelpers.TokenTypeToIndex, range, options, CancellationToken.None); var expectedResults = new LSP.SemanticTokens { @@ -131,7 +105,7 @@ public async Task TestGetSemanticTokensRange_MultiLineComment_IncludeSyntacticCl var range = new LSP.Range { Start = new Position(0, 0), End = new Position(4, 0) }; var options = ClassificationOptions.Default; var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( - document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); + document, SemanticTokensHelpers.TokenTypeToIndex, range, options, CancellationToken.None); var expectedResults = new LSP.SemanticTokens { @@ -152,39 +126,6 @@ public async Task TestGetSemanticTokensRange_MultiLineComment_IncludeSyntacticCl AssertEx.Equal(ConvertToReadableFormat(expectedResults.Data), ConvertToReadableFormat(results)); } - [Theory, CombinatorialData] - public async Task TestGetSemanticTokensRange_StringLiteralAsync(bool mutatingLspWorkspace) - { - var markup = -@"{|caret:|}class C -{ - void M() - { - var x = @""one -two """" -three""; - } -} -"; - - await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace); - var range = new LSP.Range { Start = new Position(0, 0), End = new Position(9, 0) }; - var results = await RunGetSemanticTokensRangeAsync(testLspServer, testLspServer.GetLocations("caret").First(), range); - - var expectedResults = new LSP.SemanticTokens - { - Data = new int[] - { - // Line | Char | Len | Token type | Modifier - 4, 8, 3, SemanticTokensHelpers.TokenTypeToIndex[ClassificationTypeNames.Keyword], 0, // 'var' - 1, 4, 2, SemanticTokensHelpers.TokenTypeToIndex[ClassificationTypeNames.StringEscapeCharacter], 0, // '""' - }, - }; - - await VerifyBasicInvariantsAndNoMultiLineTokens(testLspServer, results.Data!).ConfigureAwait(false); - AssertEx.Equal(ConvertToReadableFormat(expectedResults.Data), ConvertToReadableFormat(results.Data)); - } - [Theory, CombinatorialData] public async Task TestGetSemanticTokensRange_StringLiteral_IncludeSyntacticClassificationsAsync(bool mutatingLspWorkspace) { @@ -206,7 +147,7 @@ void M() var range = new LSP.Range { Start = new Position(0, 0), End = new Position(9, 0) }; var options = ClassificationOptions.Default; var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( - document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); + document, SemanticTokensHelpers.TokenTypeToIndex, range, options, CancellationToken.None); var expectedResults = new LSP.SemanticTokens { @@ -259,7 +200,7 @@ void M() var range = new LSP.Range { Start = new Position(0, 0), End = new Position(9, 0) }; var options = ClassificationOptions.Default; var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( - document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); + document, SemanticTokensHelpers.TokenTypeToIndex, range, options, CancellationToken.None); var expectedResults = new LSP.SemanticTokens { @@ -326,7 +267,7 @@ void M() var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var options = ClassificationOptions.Default; var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( - document, SemanticTokensHelpers.TokenTypeToIndex, range: null, options, includeSyntacticClassifications: true, CancellationToken.None); + document, SemanticTokensHelpers.TokenTypeToIndex, range: null, options: options, cancellationToken: CancellationToken.None); var expectedResults = new LSP.SemanticTokens { diff --git a/src/Features/Lsif/Generator/Generator.cs b/src/Features/Lsif/Generator/Generator.cs index 0c6033555dfc5..75fbf4e095626 100644 --- a/src/Features/Lsif/Generator/Generator.cs +++ b/src/Features/Lsif/Generator/Generator.cs @@ -445,9 +445,8 @@ void MarkImplementationOfSymbol(ISymbol baseMember) document, SemanticTokensHelpers.TokenTypeToIndex, range: null, - Classification.ClassificationOptions.Default, - includeSyntacticClassifications: true, - CancellationToken.None); + options: Classification.ClassificationOptions.Default, + cancellationToken: CancellationToken.None); var semanticTokensResult = new SemanticTokensResult(new SemanticTokens { Data = data }, idFactory); var semanticTokensEdge = Edge.Create(Methods.TextDocumentSemanticTokensFullName, documentVertex.GetId(), semanticTokensResult.GetId(), idFactory); diff --git a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs index 3ec0a99d2729e..13c3f3ac833b5 100644 --- a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs +++ b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs @@ -237,6 +237,7 @@ public bool TryFetch(LocalUserRegistryOptionPersister persister, OptionKey2 opti {"csharp_using_directive_placement", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferredUsingDirectivePlacement")}, {"dotnet_provide_date_and_time_completions", new RoamingProfileStorage("TextEditor.%LANGUAGE%.Specific.ProvideDateAndTimeCompletions")}, {"dotnet_log_telemetry_for_background_analyzer_execution", new FeatureFlagStorage(@"Roslyn.LogTelemetryForBackgroundAnalyzerExecution")}, + {"dotnet_lightbulb_skip_executing_deprioritized_analyzers", new FeatureFlagStorage(@"Roslyn.LightbulbSkipExecutingDeprioritizedAnalyzers")}, {"dotnet_enable_lsp_pull_diagnostics", new FeatureFlagStorage(@"Lsp.PullDiagnostics")}, #pragma warning disable CS0612 // Type or member is obsolete {"dotnet_auto_xml_doc_comment_generation", new RoamingProfileStorage("TextEditor.%LANGUAGE%.Specific.Automatic XML Doc Comment Generation", "TextEditor.VisualBasic.Specific.AutoComment")}, diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index 4227bcc28e5ba..4e3f516cc527b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Povolit osnovu dokumentu (experimentální, vyžaduje restartování) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Upřednostňovat člena struktury jen pro čtení @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Synchronizovat změny oborů názvů diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index f85dcc279d83c..bb6ace886c612 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Dokumentgliederung aktivieren (experimentell, Neustart erforderlich) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Schreibgeschützten Strukturmember bevorzugen @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Änderungen an Synchronisierungsnamespaces diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index 731fe2ea7ee80..e498d9609eb02 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Habilitar esquema de documento (experimental, requiere reinicio) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Preferir miembro de estructura de solo lectura @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Sincronizar cambios de espacios de nombres diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index a589d0d1ac9d3..9ef8d74b4d168 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Activer le plan du document (expérimental, nécessite un redémarrage) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Préférer le membre struct en lecture seule @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Synchroniser les modifications apportées aux espaces de noms diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index 97171a34668ad..ec360d23135c5 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Abilita struttura documento (sperimentale, richiede il riavvio) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Preferisci membri struct di sola lettura @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Sincronizza le modifiche di spazi dei nomi diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index 408287b39cbe9..0d1336718f1f4 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + ドキュメント アウトラインを有効にする (試験段階、再起動が必要) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + 読み取り専用構造体メンバーを優先する @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + 名前空間の変更の同期 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index 661cc860f58b9..349f24c071817 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + 문서 개요 사용(실험적, 다시 시작해야 함) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + 읽기 전용 구조체 멤버 선호 @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + 동기화 네임스페이스 변경 내용 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index e0b305a26462c..91c994e7304db 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Włącz konspekt dokumentu (eksperymentalne, wymaga ponownego uruchomienia) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Preferuj składową struktury tylko do odczytu @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Synchronizuj zmiany przestrzeni nazw diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 1b8ce4aac4742..86052411d481c 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Habilitar resumo do documento (experimental, requer reinicialização) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Preferir membro de struct somente leitura @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Sincronizar alterações de namespaces diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index cd3eb9d15a35e..e9ac7c09832bd 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + Включить структуру документа (экспериментальная функция, требуется перезапуск) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Предпочитать элемент структуры только для чтения @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + Синхронизация изменений пространств имен diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index d039cd69762e4..5989855fecd98 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + Salt okunur yapı üyesini tercih et diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index bc4ba6175e54b..54b8e370c623d 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + 启用文档大纲(实验性,需要重启) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + 首选只读结构成员 @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + 同步命名空间更改 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index d3c11e8b49366..d6195861cd0fd 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -429,7 +429,7 @@ Enable document outline (experimental, requires restart) - Enable document outline (experimental, requires restart) + 啟用文件大綱 (實驗性,需要重新開機) @@ -1149,7 +1149,7 @@ Prefer read-only struct member - Prefer read-only struct member + 偏好唯讀結構成員 @@ -1494,7 +1494,7 @@ Sync namespaces changes - Sync namespaces changes + 同步處理命名空間變更 diff --git a/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb b/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb index 7f76efcc70b3a..cb13a26206308 100644 --- a/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb +++ b/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb @@ -667,7 +667,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics Public Sub Reanalyze(workspace As Workspace, Optional projectIds As IEnumerable(Of ProjectId) = Nothing, Optional documentIds As IEnumerable(Of DocumentId) = Nothing, Optional highPriority As Boolean = False) Implements IDiagnosticAnalyzerService.Reanalyze End Sub - Public Function GetDiagnosticsForSpanAsync(document As TextDocument, range As TextSpan?, shouldIncludeDiagnostic As Func(Of String, Boolean), includeCompilerDiagnostics As Boolean, Optional includeSuppressedDiagnostics As Boolean = False, Optional priority As CodeActionRequestPriority = CodeActionRequestPriority.None, Optional addOperationScope As Func(Of String, IDisposable) = Nothing, Optional diagnosticKinds As DiagnosticKind = DiagnosticKind.All, Optional isExplicit As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As Task(Of ImmutableArray(Of DiagnosticData)) Implements IDiagnosticAnalyzerService.GetDiagnosticsForSpanAsync + Public Function GetDiagnosticsForSpanAsync(document As TextDocument, range As TextSpan?, shouldIncludeDiagnostic As Func(Of String, Boolean), includeCompilerDiagnostics As Boolean, Optional includeSuppressedDiagnostics As Boolean = False, Optional priority As ICodeActionRequestPriorityProvider = Nothing, Optional addOperationScope As Func(Of String, IDisposable) = Nothing, Optional diagnosticKinds As DiagnosticKind = DiagnosticKind.All, Optional isExplicit As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As Task(Of ImmutableArray(Of DiagnosticData)) Implements IDiagnosticAnalyzerService.GetDiagnosticsForSpanAsync Return SpecializedTasks.EmptyImmutableArray(Of DiagnosticData) End Function @@ -699,7 +699,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics Throw New NotImplementedException() End Function - Public Function TryGetDiagnosticsForSpanAsync(document As TextDocument, range As TextSpan, shouldIncludeDiagnostic As Func(Of String, Boolean), Optional includeSuppressedDiagnostics As Boolean = False, Optional priority As CodeActionRequestPriority = CodeActionRequestPriority.None, Optional diagnosticKinds As DiagnosticKind = DiagnosticKind.All, Optional isExplicit As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As Task(Of (diagnostics As ImmutableArray(Of DiagnosticData), upToDate As Boolean)) Implements IDiagnosticAnalyzerService.TryGetDiagnosticsForSpanAsync + Public Function TryGetDiagnosticsForSpanAsync(document As TextDocument, range As TextSpan, shouldIncludeDiagnostic As Func(Of String, Boolean), Optional includeSuppressedDiagnostics As Boolean = False, Optional priority As ICodeActionRequestPriorityProvider = Nothing, Optional diagnosticKinds As DiagnosticKind = DiagnosticKind.All, Optional isExplicit As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As Task(Of (diagnostics As ImmutableArray(Of DiagnosticData), upToDate As Boolean)) Implements IDiagnosticAnalyzerService.TryGetDiagnosticsForSpanAsync Return Task.FromResult((ImmutableArray(Of DiagnosticData).Empty, False)) End Function End Class diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs index 78754519210e5..cdedfa9553abf 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs @@ -5,7 +5,6 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis; @@ -46,9 +45,6 @@ public Task GetValueAsync(LoadTextOptions options, CancellationT public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out TextAndVersion value) => TryGetValue(out value); - //public bool TryGetTextVersion(out VersionStamp version) - //{ - // version = Value.Version; - // return true; - //} + public ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) + => new(_value.Version); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs index 155d4a326ae09..9fd34212f2623 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs @@ -649,7 +649,7 @@ public bool TryGetTopLevelChangeTextVersion(out VersionStamp version) } } - public override async Task GetTopLevelChangeTextVersionAsync(CancellationToken cancellationToken) + public override async ValueTask GetTopLevelChangeTextVersionAsync(CancellationToken cancellationToken) { if (_treeSource == null) { diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs index 16bc4f27b467c..403fc2f57ce5c 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs @@ -60,6 +60,9 @@ public bool TryGetTextVersion(LoadTextOptions options, out VersionStamp version) version = _version; return version != default; } + + public ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) + => new(_version); } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs index c6b8eb49fb6d8..0e4b9676e69c5 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs @@ -19,4 +19,10 @@ internal interface ITextAndVersionSource bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out TextAndVersion value); TextAndVersion GetValue(LoadTextOptions options, CancellationToken cancellationToken); Task GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken); + + /// + /// Retrieves just the version information from this instance. Cheaper than when only + /// the version is needed, and avoiding loading the text is desirable. + /// + ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs index ba38c0915c6e8..c0ab70015feb1 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs @@ -68,4 +68,10 @@ public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out Text public Task GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken) => GetLazyValue(options).GetValueAsync(cancellationToken); + + public async ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) + { + var value = await GetValueAsync(options, cancellationToken).ConfigureAwait(false); + return value.Version; + } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs b/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs index ee5645a5bb545..54b0ed3a5de03 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; @@ -89,14 +88,19 @@ public bool TryGetTextVersion(LoadTextOptions options, out VersionStamp version) return false; } - public TextAndVersion GetValue(LoadTextOptions options, CancellationToken cancellationToken) + private async ValueTask GetRecoverableTextAsync( + bool useAsync, LoadTextOptions options, CancellationToken cancellationToken) { if (_initialSourceOrRecoverableText is ITextAndVersionSource source) { // replace initial source with recoverable text if it hasn't been replaced already: + var textAndVersion = useAsync + ? await source.GetValueAsync(options, cancellationToken).ConfigureAwait(false) + : source.GetValue(options, cancellationToken); + Interlocked.CompareExchange( ref _initialSourceOrRecoverableText, - value: new RecoverableText(source, source.GetValue(options, cancellationToken), options, _services), + value: new RecoverableText(source, textAndVersion, options, _services), comparand: source); } @@ -105,40 +109,40 @@ public TextAndVersion GetValue(LoadTextOptions options, CancellationToken cancel var recoverableText = (RecoverableText)_initialSourceOrRecoverableText; if (recoverableText.LoadTextOptions != options && recoverableText.InitialSource != null) { + var textAndVersion = useAsync + ? await recoverableText.InitialSource.GetValueAsync(options, cancellationToken).ConfigureAwait(false) + : recoverableText.InitialSource.GetValue(options, cancellationToken); Interlocked.Exchange( ref _initialSourceOrRecoverableText, - new RecoverableText(recoverableText.InitialSource, recoverableText.InitialSource.GetValue(options, cancellationToken), options, _services)); + new RecoverableText(recoverableText.InitialSource, textAndVersion, options, _services)); } - recoverableText = (RecoverableText)_initialSourceOrRecoverableText; - return recoverableText.ToTextAndVersion(recoverableText.GetValue(cancellationToken)); + return (RecoverableText)_initialSourceOrRecoverableText; } - public async Task GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken) + public TextAndVersion GetValue(LoadTextOptions options, CancellationToken cancellationToken) { - if (_initialSourceOrRecoverableText is ITextAndVersionSource source) - { - // replace initial source with recoverable text if it hasn't been replaced already: - Interlocked.CompareExchange( - ref _initialSourceOrRecoverableText, - value: new RecoverableText(source, await source.GetValueAsync(options, cancellationToken).ConfigureAwait(false), options, _services), - comparand: source); - } +#pragma warning disable CA2012 // Use ValueTasks correctly + var valueTask = GetRecoverableTextAsync(useAsync: false, options, cancellationToken); +#pragma warning restore CA2012 // Use ValueTasks correctly + Contract.ThrowIfFalse(valueTask.IsCompleted, "GetRecoverableTextAsync should have completed synchronously since we passed 'useAsync: false'"); + var recoverableText = valueTask.GetAwaiter().GetResult(); - // If we have a recoverable text but the options it was created for do not match the current options - // and the initial source supports reloading, reload and replace the recoverable text. - var recoverableText = (RecoverableText)_initialSourceOrRecoverableText; - if (recoverableText.LoadTextOptions != options && recoverableText.InitialSource != null) - { - Interlocked.Exchange( - ref _initialSourceOrRecoverableText, - new RecoverableText(recoverableText.InitialSource, await recoverableText.InitialSource.GetValueAsync(options, cancellationToken).ConfigureAwait(false), options, _services)); - } + return recoverableText.ToTextAndVersion(recoverableText.GetValue(cancellationToken)); + } - recoverableText = (RecoverableText)_initialSourceOrRecoverableText; + public async Task GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken) + { + var recoverableText = await GetRecoverableTextAsync(useAsync: true, options, cancellationToken).ConfigureAwait(false); return recoverableText.ToTextAndVersion(await recoverableText.GetValueAsync(cancellationToken).ConfigureAwait(false)); } + public async ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) + { + var recoverableText = await GetRecoverableTextAsync(useAsync: true, options, cancellationToken).ConfigureAwait(false); + return recoverableText.Version; + } + private sealed class RecoverableText : WeaklyCachedRecoverableValueSource, ITextVersionable { private readonly ITemporaryStorageServiceInternal _storageService; diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocument.cs b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocument.cs index c2f5719101e2c..7c608cdb54d69 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocument.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocument.cs @@ -104,7 +104,7 @@ internal VersionStamp GetTextVersionSynchronously(CancellationToken cancellation /// /// Gets the version of the document's top level signature. /// - internal Task GetTopLevelChangeTextVersionAsync(CancellationToken cancellationToken = default) + internal ValueTask GetTopLevelChangeTextVersionAsync(CancellationToken cancellationToken = default) => State.GetTopLevelChangeTextVersionAsync(cancellationToken); /// diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs index 8610e1106e4c6..3362244b596fd 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs @@ -235,11 +235,8 @@ private VersionStamp GetNewerVersion() return VersionStamp.Create(); } - public virtual async Task GetTopLevelChangeTextVersionAsync(CancellationToken cancellationToken) - { - var textAndVersion = await this.TextAndVersionSource.GetValueAsync(LoadTextOptions, cancellationToken).ConfigureAwait(false); - return textAndVersion.Version; - } + public virtual ValueTask GetTopLevelChangeTextVersionAsync(CancellationToken cancellationToken) + => this.TextAndVersionSource.GetVersionAsync(LoadTextOptions, cancellationToken); /// /// Only checks if the source of the text has changed, no content check is done. diff --git a/src/Workspaces/MSBuildTest/Utilities/DotNetSdkMSBuildInstalled.cs b/src/Workspaces/MSBuildTest/Utilities/DotNetSdkMSBuildInstalled.cs index 9ee2dd19b6fa8..49d252c57b8c4 100644 --- a/src/Workspaces/MSBuildTest/Utilities/DotNetSdkMSBuildInstalled.cs +++ b/src/Workspaces/MSBuildTest/Utilities/DotNetSdkMSBuildInstalled.cs @@ -117,8 +117,10 @@ public DotNetSdkMSBuildInstalled() { } + // Eventually should revert condition to 'SdkPath is null' after MSBuild issue is fixed: + // https://github.com/dotnet/roslyn/issues/67566 public override bool ShouldSkip - => SdkPath is null; + => true; public override string SkipReason #if NETCOREAPP diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.cs.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.cs.xlf index b02cd431c80ef..155a5994c7aa4 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.cs.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.cs.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Služba responzivity diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.de.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.de.xlf index dc98fd0d2bd05..804cc0ce80461 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.de.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.de.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Keepalive-Dienst diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.es.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.es.xlf index 5462f0b6ee992..584bb03d4d001 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.es.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.es.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Mantener el servicio activo diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.fr.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.fr.xlf index bb4256bbd65ba..b5ad91fb1d725 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.fr.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.fr.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Maintenir le service actif diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.it.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.it.xlf index 0d305f15d9861..88e2c9fc78a89 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.it.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.it.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Servizio keep-alive diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ja.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ja.xlf index 9ae6fad18e875..8f6ad1d4f644c 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ja.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ja.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + キープ アライブ サービス diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ko.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ko.xlf index d4cc003419926..30bf7c556bdc3 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ko.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ko.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + 서비스 연결 유지 diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pl.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pl.xlf index 05827cf1a77f4..f592ab5b07756 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pl.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pl.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Utrzymywanie aktywności usługi diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf index fc98888570ad6..cb2748648b8d0 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Serviço Keep alive diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ru.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ru.xlf index 93bc2cfd34c2e..d0cb3d6b7f5ba 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ru.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.ru.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Служба проверки активности diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.tr.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.tr.xlf index a9158ec89148d..9a18798cb3fe7 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.tr.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.tr.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + Etkin tutma hizmeti diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hans.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hans.xlf index 13ddd0d6b3672..529893362502c 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hans.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hans.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + 保持活动状态的服务 diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hant.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hant.xlf index ddf4141b3b8c1..f03939cc394ee 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hant.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.zh-Hant.xlf @@ -84,7 +84,7 @@ Keep alive service - Keep alive service + 保持運作服務 diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.cs.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.cs.xlf index ebe7fcc8962ee..efe571136f0c6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.cs.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.cs.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Nejde generovat kód pro nepodporovaný operátor {0}. @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Nenašlo se umístění, do kterého by se vygeneroval symbol. Destination location was from a different tree. - Destination location was from a different tree. + Cílové umístění pochází z jiného stromu. Destination location was not in source. - Destination location was not in source. + Cílové umístění není ve zdroji. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Cílový typ musí být {0}, {1}, {2} nebo {3}, ale zadaný typ je {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Cílový typ musí být {0}, {1} nebo {2}, ale zadaný typ je {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Cílový typ musí být {0}, ale zadaný typ je {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Cílový typ musí být {0} nebo {1}, ale zadaný typ je {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Neplatný počet parametrů pro binární operátor Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Neplatný počet parametrů pro unární operátor Location must be null or from source. - Location must be null or from source. + Umístění musí být null nebo ze zdroje. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Obor názvů nejde přidat do tohoto cílového umístění. No available location found to add statements to. - No available location found to add statements to. + Nenašlo se dostupné umístění, kam by se daly přidávat příkazy. No location provided to add statements to. - No location provided to add statements to. + Není zadané žádné umístění, kam by se daly přidávat příkazy. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.de.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.de.xlf index 68b8128595288..b0b1a72f702f6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.de.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.de.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Kann keinen Code für nicht unterstützten Operator "{0}" generieren @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Konnte keinen Ort finden, in den das Symbol generiert werden kann. Destination location was from a different tree. - Destination location was from a different tree. + Zielort stammt aus anderem Baum. Destination location was not in source. - Destination location was not in source. + Zielort war nicht in Quelle. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Der Zieltyp muss "{0}", "{1}", "{2}" oder "{3}" lauten. Es wurde jedoch "{4}" angegeben. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Zieltyp muss {0}, {1} oder {2} sein. Es wurde jedoch {3} angegeben. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Zieltyp muss {0} sein. Es wurde jedoch {1} angegeben. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Zieltyp muss {0} oder {1} sein. Es wurde jedoch {2} angegeben. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Ungültige Parameteranzahl für binären Operator. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Ungültige Parameteranzahl für unären Operator. Location must be null or from source. - Location must be null or from source. + Ort muss null oder von Quelle sein. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Namespace kann zu diesem Ziel nicht hinzugefügt werden. No available location found to add statements to. - No available location found to add statements to. + Kein verfügbarer Speicherort zum Hinzufügen von Anweisungen gefunden. No location provided to add statements to. - No location provided to add statements to. + Kein Ort angegeben, zu dem Anweisungen hinzugefügt werden. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.es.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.es.xlf index 7ede30a88e105..9f00f78f891d5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.es.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.es.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + No se puede generar código para el operador no compatible '{0}' @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + No se pudo encontrar una ubicación en la que generar un símbolo. Destination location was from a different tree. - Destination location was from a different tree. + La ubicación de destino era de otro árbol. Destination location was not in source. - Destination location was not in source. + La ubicación de destino no estaba en el código fuente. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + El tipo de destino debe ser una instancia de {0}, {1}, {2} o {3}, pero el proporcionado es {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + El tipo de destino debe ser un {0}, {1} o {2}, pero el proporcionado es {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + El tipo de destino debe ser un {0}, pero el proporcionado es {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + El tipo de destino debe ser un {0} o un {1}, pero el proporcionado es {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Número de parámetros no válido para el operador binario. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Número de parámetros no válido para el operador unario. Location must be null or from source. - Location must be null or from source. + La ubicación debe ser null o del código fuente. Namespace can not be added in this destination. - Namespace can not be added in this destination. + El espacio de nombres no se puede agregar en este destino. No available location found to add statements to. - No available location found to add statements to. + No hay ubicación disponible a la que agregar declaraciones. No location provided to add statements to. - No location provided to add statements to. + No se ha proporcionado ubicación a la que agregar instrucciones. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.fr.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.fr.xlf index 7e072cdec9a3a..3d488955f4868 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.fr.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.fr.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Impossible de générer du code pour l'opérateur non pris en charge '{0}' @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + L'emplacement dans lequel générer le symbole est introuvable. Destination location was from a different tree. - Destination location was from a different tree. + L'emplacement de destination provient d'une arborescence différente. Destination location was not in source. - Destination location was not in source. + L'emplacement de destination n'était pas dans la source. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Le type de destination doit être {0}, {1}, {2} ou {3}, mais le type spécifié est {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Le type de destination doit être un {0}, {1} ou {2}, mais le type donné est {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Le type de destination doit être un {0}, mais le type donné est {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Le type de destination doit être un {0} ou un {1}, mais le type donné est {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Nombre de paramètres non valide pour l'opérateur binaire. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Nombre de paramètres non valide pour l'opérateur unaire. Location must be null or from source. - Location must be null or from source. + L'emplacement doit être null ou dans la source. Namespace can not be added in this destination. - Namespace can not be added in this destination. + L'espace de noms ne peut pas être ajouté dans cette destination. No available location found to add statements to. - No available location found to add statements to. + Aucun emplacement trouvé pour ajouter des instructions. No location provided to add statements to. - No location provided to add statements to. + Aucun emplacement n'a été fourni pour l'ajout d'instructions. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.it.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.it.xlf index 2626cff337287..08c7cb4a54ff7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.it.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.it.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Non è possibile generare il codice per l'operatore '{0}' non supportato @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Non è stata trovata la posizione in cui generare il simbolo. Destination location was from a different tree. - Destination location was from a different tree. + La posizione di destinazione è in un albero diverso. Destination location was not in source. - Destination location was not in source. + La posizione di destinazione non è inclusa nell'origine. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Il tipo di destinazione deve essere {0}, {1}, {2} o {3}, ma quello specificato è {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Il tipo di destinazione deve essere {0}, {1} o {2}, ma quello specificato è {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Il tipo di destinazione deve essere {0}, ma quello specificato è {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Il tipo di destinazione deve essere {0} o {1}, ma quello specificato è {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Il numero di parametri per l'operatore binario non è valido. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Il numero di parametri per l'operatore unario non è valido. Location must be null or from source. - Location must be null or from source. + La posizione deve essere Null o derivare dall'origine. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Non è possibile aggiungere lo spazio dei nomi in questa destinazione. No available location found to add statements to. - No available location found to add statements to. + Non sono state trovate posizioni disponibili in cui aggiungere istruzioni. No location provided to add statements to. - No location provided to add statements to. + Non sono state specificate posizioni in cui aggiungere istruzioni. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ja.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ja.xlf index c1336ec5cec81..f44a80cebe053 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ja.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ja.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + サポートされない演算子 '{0}' のコードは生成できません @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + シンボルの生成先が見つかりませんでした。 Destination location was from a different tree. - Destination location was from a different tree. + ターゲットの場所は、別のツリーでした。 Destination location was not in source. - Destination location was not in source. + 追加先の場所は、ソース内ではありません。 Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + ターゲットの型は {0}、{1}、{2}、または {3} である必要がありますが、{4} が指定されています。 Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + ターゲットの型は {0}、{1}、または {2} である必要がありますが、{3} が指定されています。 Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + ターゲットの型は {0} である必要がありますが、{1} が指定されています。 Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + ターゲットの型は {0} または {1} である必要がありますが、{2} が指定されています。 @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + 二項演算子のパラメーターの数が無効です。 Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + 単項演算子のパラメーターの数が無効です。 Location must be null or from source. - Location must be null or from source. + 場所は Null であるか、ソースからでなければなりません。 Namespace can not be added in this destination. - Namespace can not be added in this destination. + 名前空間は、このターゲットでは追加できません。 No available location found to add statements to. - No available location found to add statements to. + ステートメントを追加する場所がありません。 No location provided to add statements to. - No location provided to add statements to. + ステートメントを追加する場所がありません。 diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ko.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ko.xlf index e0a30e9214c4b..72bb36a8d2a9a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ko.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ko.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + 지원되지 않는 '{0}' 연산자에 대한 코드를 생성할 수 없습니다. @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + 기호를 생성할 위치를 찾을 수 없습니다. Destination location was from a different tree. - Destination location was from a different tree. + 다른 트리에서 온 대상 위치입니다. Destination location was not in source. - Destination location was not in source. + 대상 위치가 소스에 없습니다. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + 대상 형식은 {0}, {1}, {2} 또는 {3}이어야 하지만 지정된 대상 형식은 {4}입니다. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + 대상 형식은 {0}, {1} 또는 {2}이어야 하지만 지정된 형식은 {3}입니다. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + 대상 형식은 {0}이어야 하지만 지정된 형식은 {1}입니다. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + 대상 형식은 {0} 또는 {1}이어야 하지만 지정된 형식은 {2}입니다. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + 이진 연산자에 대해 잘못된 매개 변수 수입니다. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + 단항 연산자에 대해 잘못된 매개 변수 수입니다. Location must be null or from source. - Location must be null or from source. + 위치는 null이거나 소스에 있어야 합니다. Namespace can not be added in this destination. - Namespace can not be added in this destination. + 이 대상에는 네임스페이스를 추가할 수 없습니다. No available location found to add statements to. - No available location found to add statements to. + 문을 추가할 위치가 없습니다. No location provided to add statements to. - No location provided to add statements to. + 문을 추가할 위치가 제공되지 않았습니다. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pl.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pl.xlf index 6fff9115181da..879d216c57490 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pl.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pl.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Nie można wygenerować kodu dla nieobsługiwanego operatora „{0}” @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Nie można znaleźć lokalizacji do wygenerowania symbolu. Destination location was from a different tree. - Destination location was from a different tree. + Lokalizacja docelowa pochodziła z innego drzewa. Destination location was not in source. - Destination location was not in source. + Lokalizacja docelowa nie znajdowała się w źródle. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Typ docelowy musi być elementem {0}, {1}, {2} lub {3}, ale podano element {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Typ docelowy musi być elementem {0}, {1} lub {2}, ale podano element {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Typ docelowy musi być elementem {0}, ale podano element {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Typ docelowy musi być elementem {0} lub {1}, ale podano element {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Nieprawidłowa liczba parametrów operatora binarnego. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Nieprawidłowa liczba parametrów operatora jednoargumentowego. Location must be null or from source. - Location must be null or from source. + Lokalizacja musi mieć wartość null lub pochodzić ze źródła. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Do tego miejsca docelowego nie można dodać przestrzeni nazw. No available location found to add statements to. - No available location found to add statements to. + Nie znaleziono dostępnej lokalizacji, do której można dodać instrukcje. No location provided to add statements to. - No location provided to add statements to. + Nie podano lokalizacji, do których można dodać instrukcje. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pt-BR.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pt-BR.xlf index 845bcb94cf683..7b3c34b92872c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pt-BR.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.pt-BR.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Não é possível gerar código para operador não suportado "{0}" @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Não foi possível encontrar o local para o símbolo de geração. Destination location was from a different tree. - Destination location was from a different tree. + Local de destino era de uma árvore diferente. Destination location was not in source. - Destination location was not in source. + Local de destino não estava na origem. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + O tipo de destino precisa ser {0}, {1}, {2} ou {3}, mas o tipo fornecido é {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + O tipo de destino deve ser um {0}, {1} ou {2}, mas o tipo fornecido é {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + O tipo de destino deve ser um {0}, mas o tipo fornecido é {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + O tipo de destino deve ser um {0} ou um {1}, mas o tipo fornecido é {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Número inválido de parâmetros para o operador binário. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Número inválido de parâmetros para o operador unário. Location must be null or from source. - Location must be null or from source. + Local deve ser nulo ou da fonte. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Namespace não pode ser adicionado nesse destino. No available location found to add statements to. - No available location found to add statements to. + Nenhum local disponível encontrado para adicionar instruções. No location provided to add statements to. - No location provided to add statements to. + Nenhum local fornecido para o qual adicionar instruções. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ru.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ru.xlf index f358ba106b395..b4b4b41917894 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ru.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.ru.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Невозможно сформировать код для неподдерживаемого оператора "{0}" @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Не удалось найти расположение для создания символа. Destination location was from a different tree. - Destination location was from a different tree. + Целевое расположение находилось в другом дереве. Destination location was not in source. - Destination location was not in source. + Целевое расположение не найдено в источнике. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Конечный тип должен быть {0}, {1}, {2} или {3}, но указан {4}. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Конечный тип должен быть {0}, {1} или {2}, но указан {3}. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Конечный тип должен быть {0}, но указан {1}. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Конечный тип должен быть {0} или {1}, но указан {2}. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + Недопустимое число параметров для бинарного оператора. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Недопустимое число параметров для унарного оператора. Location must be null or from source. - Location must be null or from source. + Расположение должно иметь значение Null или источника. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Не удается добавить пространство имен в этот конечный объект. No available location found to add statements to. - No available location found to add statements to. + Доступные места для добавления операторов не обнаружены. No location provided to add statements to. - No location provided to add statements to. + Для добавления операторов не было указано расположение. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.tr.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.tr.xlf index 4bb232206a3fd..965ed9cf8460c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.tr.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.tr.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + Desteklenmeyen operatör '{0}' için kod üretilemiyor @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + Sembolün üretileceği konum bulunamadı. Destination location was from a different tree. - Destination location was from a different tree. + Hedef konum farklı bir ağaçtandı. Destination location was not in source. - Destination location was not in source. + Hedef konum kaynakta değildi. Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + Hedef tür bir {0}, {1}, {2} veya {3} olmalı, ancak {4} belirtildi. Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + Hedef tür bir {0}, {1} veya {2} olmalı, ancak {3} belirtildi. Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + Hedef tür bir {0} olmalı, ancak {1} belirtildi. Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + Hedef tür bir {0} veya {1} olmalı, ancak {2} belirtildi. @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + İkili operatör için parametre sayısı geçersiz. Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + Birli operatör için parametre sayısı geçersiz. Location must be null or from source. - Location must be null or from source. + Konum boş veya kaynağa ait olmalıdır. Namespace can not be added in this destination. - Namespace can not be added in this destination. + Ad alanı bu hedefe eklenemez. No available location found to add statements to. - No available location found to add statements to. + Deyimlerin ekleneceği kullanılabilir konum bulunamadı. No location provided to add statements to. - No location provided to add statements to. + Deyimlerin ekleneceği konum sağlanmadı. diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hans.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hans.xlf index 9d6fb60801106..72372bcb130ea 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hans.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hans.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + 无法为不受支持的运算符“{0}”生成代码 @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + 找不到符号生成到的位置。 Destination location was from a different tree. - Destination location was from a different tree. + 目标位置来自不同的树。 Destination location was not in source. - Destination location was not in source. + 目标位置不在源中。 Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + 目标类型必须是 {0}、{1}、{2} 或 {3},但给定类型是 {4}。 Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + 目标类型必须是 {0}、{1} 或 {2},但给定类型是 {3}。 Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + 目标类型必须是 {0},但给定类型是 {1}。 Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + 目标类型必须是 {0} 或 {1},但给定类型是 {2}。 @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + 参数数目对二元运算符无效。 Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + 参数数目对一元运算符无效。 Location must be null or from source. - Location must be null or from source. + 位置必须为 null 或来自源。 Namespace can not be added in this destination. - Namespace can not be added in this destination. + 不能在此目标中添加命名空间。 No available location found to add statements to. - No available location found to add statements to. + 没有找到添加语句的可用位置。 No location provided to add statements to. - No location provided to add statements to. + 未提供语句要添加到的位置。 diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hant.xlf b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hant.xlf index fed277e7f72f6..39acdd06f8340 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hant.xlf +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/xlf/WorkspaceExtensionsResources.zh-Hant.xlf @@ -4,7 +4,7 @@ Cannot generate code for unsupported operator '{0}' - Cannot generate code for unsupported operator '{0}' + 無法產生不受支援之運算子 '{0}' 的程式碼 @@ -14,37 +14,37 @@ Could not find location to generation symbol into. - Could not find location to generation symbol into. + 找不到產生符號目的地位置。 Destination location was from a different tree. - Destination location was from a different tree. + 目的地位置來自不同的樹狀目錄。 Destination location was not in source. - Destination location was not in source. + 目的地位置不在來源中。 Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. - Destination type must be a {0}, {1}, {2} or {3}, but given one is {4}. + 目的地類型必須是 {0}、{1}、{2} 或 {3},但提供的類型是 {4}。 Destination type must be a {0}, {1} or {2}, but given one is {3}. - Destination type must be a {0}, {1} or {2}, but given one is {3}. + 目的地類型必須是 {0}、{1} 或 {2},但提供的是 {3}。 Destination type must be a {0}, but given one is {1}. - Destination type must be a {0}, but given one is {1}. + 目的地類型必須是 {0},但提供的是 {1}。 Destination type must be a {0} or a {1}, but given one is {2}. - Destination type must be a {0} or a {1}, but given one is {2}. + 目的地類型必須是 {0} 或 {1},但提供的是 {2}。 @@ -84,32 +84,32 @@ Invalid number of parameters for binary operator. - Invalid number of parameters for binary operator. + 二元運算子的參數數目無效。 Invalid number of parameters for unary operator. - Invalid number of parameters for unary operator. + 一元運算子的參數數目無效。 Location must be null or from source. - Location must be null or from source. + 位置必須是 null 或源自來源。 Namespace can not be added in this destination. - Namespace can not be added in this destination. + 無法將命名空間加入此目的地。 No available location found to add statements to. - No available location found to add statements to. + 找不到能加入陳述式的可用位置。 No location provided to add statements to. - No location provided to add statements to. + 未提供加入陳述式的位置。 From 15b0d1d796734fc8203a7d1970483f83f24e9265 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Tue, 4 Apr 2023 21:30:07 +0000 Subject: [PATCH 139/261] Merged PR 30345: Hook up fault telemetry initialize if it's available Hook up fault telemetry initialize if it's available. This now fully works as long as the right binaries are manually added to the extension folder * [X] Tested with and without binaries being available * [X] Tested that nupkg is produced with right dependencies * [ ] Add as an ILogger implementation to report telemetry * [ ] NPM package is produced --- Roslyn.sln | 2 +- eng/config/PublishData.json | 2 +- .../Program.cs | 8 + .../Protocol/ILspFaultLogger.cs | 2 +- ...odeAnalysis.LanguageServer.Protocol.csproj | 2 +- ...odeAnalysis.LanguageServer.Internal.csproj | 48 +++++ ...t.CodeAnalysis.LanguageServer.Internal.sln | 25 +++ .../VSCodeTelemetryLogger.cs | 168 ++++++++++++++++++ .../package.json | 4 + .../Microsoft.CodeAnalysis.Workspaces.csproj | 2 +- ...soft.CodeAnalysis.Remote.ServiceHub.csproj | 1 - 11 files changed, 258 insertions(+), 6 deletions(-) create mode 100644 src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj create mode 100644 src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.sln create mode 100644 src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs create mode 100644 src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/package.json diff --git a/Roslyn.sln b/Roslyn.sln index 4d225dbb22842..e53fd128ca5cc 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -533,7 +533,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Too EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LanguageServer", "LanguageServer", "{D449D505-CC6A-4E0B-AF1B-976E2D0AE67A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServer.Internal", "src\VisualStudio\Microsoft.VisualStudio.LanguageServer.Internal\Microsoft.VisualStudio.LanguageServer.Internal.csproj", "{9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.Internal", "src\VisualStudio\Microsoft.CodeAnalysis.LanguageServer.Internal\Microsoft.CodeAnalysis.LanguageServer.Internal.csproj", "{9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/eng/config/PublishData.json b/eng/config/PublishData.json index 3df62fd787481..6a855565a9f2e 100644 --- a/eng/config/PublishData.json +++ b/eng/config/PublishData.json @@ -42,7 +42,7 @@ "Microsoft.CodeAnalysis.EditorFeatures.Wpf": "vssdk", "Microsoft.CodeAnalysis.EditorFeatures.Cocoa": "vssdk", "Microsoft.VisualStudio.IntegrationTest.Utilities": "vs-impl", - "Microsoft.VisualStudio.LanguageServer.Internal": "npm", + "Microsoft.CodeAnalysis.LanguageServer.Internal": "npm", "Microsoft.CodeAnalysis.LanguageServer.Protocol": "vs-impl", "Microsoft.CodeAnalysis.CSharp.LanguageServer.Protocol": "vs-impl", "Microsoft.CodeAnalysis.VisualBasic.LanguageServer.Protocol": "vs-impl", diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 01c62c17b0daf..7923007ab9032 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.LanguageServer.StarredSuggestions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; +using Microsoft.VisualStudio.Composition; Console.Title = "Microsoft.CodeAnalysis.LanguageServer"; var parser = CreateCommandLineParser(); @@ -67,6 +68,13 @@ static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); + // Initialize the fault handler if it's available + try + { + exportProvider.GetExportedValue()?.Initialize(); + } + catch (CompositionFailedException) { } + // Cancellation token source that we can use to cancel on either LSP server shutdown (managed by client) or interrupt. using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); cancellationToken = cancellationTokenSource.Token; diff --git a/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs b/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs index 3c274964f1fb9..a94154d783800 100644 --- a/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs +++ b/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs @@ -10,5 +10,5 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal interface ILspFaultLogger { void Initialize(); - void LogFault(Exception exception, LogLevel logLevel, bool forceDump); + void ReportFault(Exception exception, LogLevel logLevel, bool forceDump); } diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index b548bde1d5c77..cc108c2d8617c 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -65,7 +65,7 @@ - + diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj new file mode 100644 index 0000000000000..4a30e5ad9c21e --- /dev/null +++ b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj @@ -0,0 +1,48 @@ + + + + + Library + net6.0 + enable + true + + .NET Compiler Platform ("Roslyn") Language Server Protocol internal. + + + + + + + + + + + $(StageForNpmPackDependsOn);CollectNpmInputs + + + + + $(PackageVersion) + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.sln b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.sln new file mode 100644 index 0000000000000..896c35f035f63 --- /dev/null +++ b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.001.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.Internal", "Microsoft.CodeAnalysis.LanguageServer.Internal.csproj", "{A8FD3BA8-E5CE-4BCE-B7D2-5392F904CB6D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A8FD3BA8-E5CE-4BCE-B7D2-5392F904CB6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8FD3BA8-E5CE-4BCE-B7D2-5392F904CB6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8FD3BA8-E5CE-4BCE-B7D2-5392F904CB6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8FD3BA8-E5CE-4BCE-B7D2-5392F904CB6D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B9963ADF-DDCD-4E0B-85CC-2DA76B73A330} + EndGlobalSection +EndGlobal diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs new file mode 100644 index 0000000000000..4c32ff2b0ae51 --- /dev/null +++ b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs @@ -0,0 +1,168 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Composition; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.CodeAnalysis.Telemetry; +using Microsoft.VisualStudio.Telemetry; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.Internal; + +[Export(typeof(ILspFaultLogger)), Shared] +internal class VSCodeWorkspaceTelemetryService : ILspFaultLogger +{ + private TelemetrySession? _telemetrySession; + private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; + + private static readonly ConcurrentDictionary s_eventMap = new(); + private static readonly ConcurrentDictionary<(FunctionId id, string name), string> s_propertyMap = new(); + + private int _dumpsSubmitted = 0; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSCodeWorkspaceTelemetryService() + { + } + + public void Initialize() + { + _telemetrySession = TelemetryService.CreateAndGetDefaultSession(CollectorApiKey); + _telemetrySession.Start(); + + FatalError.Handler = (exception, severity, forceDump) => ReportFault(exception, ConvertSeverity(severity), forceDump); + FatalError.CopyHandlerTo(typeof(Compilation).Assembly); + } + + public void ReportFault(Exception exception, LogLevel logLevel, bool forceDump) + { + Assumes.NotNull(_telemetrySession); + + try + { + if (exception is OperationCanceledException { InnerException: { } oceInnerException }) + { + ReportFault(oceInnerException, logLevel, forceDump); + return; + } + + if (exception is AggregateException aggregateException) + { + // We (potentially) have multiple exceptions; let's just report each of them + foreach (var innerException in aggregateException.Flatten().InnerExceptions) + ReportFault(innerException, logLevel, forceDump); + + return; + } + + var currentProcess = Process.GetCurrentProcess(); + var faultEvent = new FaultEvent( + eventName: "vs/ide/vbcs/nonfatalwatson", + description: GetDescription(exception), + ConvertToFaultSeverity(logLevel), + exceptionObject: exception, + gatherEventDetails: faultUtility => + { + if (forceDump) + { + // Let's just send a maximum of three; number chosen arbitrarily + if (Interlocked.Increment(ref _dumpsSubmitted) <= 3) + faultUtility.AddProcessDump(currentProcess.Id); + } + + if (faultUtility is FaultEvent { IsIncludedInWatsonSample: true }) + { + // if needed, add any extra logs here + } + + // Returning "0" signals that, if sampled, we should send data to Watson. + // Any other value will cancel the Watson report. We never want to trigger a process dump manually, + // we'll let TargetedNotifications determine if a dump should be collected. + // See https://aka.ms/roslynnfwdocs for more details + return 0; + }); + + _telemetrySession.PostEvent(faultEvent); + } + catch (OutOfMemoryException) + { + FailFast.OnFatalException(exception); + } + catch (Exception e) + { + FailFast.OnFatalException(e); + } + } + + private static string GetDescription(Exception exception) + { + const string CodeAnalysisNamespace = nameof(Microsoft) + "." + nameof(CodeAnalysis); + + // Be resilient to failing here. If we can't get a suitable name, just fall back to the standard name we + // used to report. + try + { + // walk up the stack looking for the first call from a type that isn't in the ErrorReporting namespace. + var frames = new StackTrace(exception).GetFrames(); + + // On the .NET Framework, GetFrames() can return null even though it's not documented as such. + // At least one case here is if the exception's stack trace itself is null. + if (frames != null) + { + foreach (var frame in frames) + { + var method = frame?.GetMethod(); + var methodName = method?.Name; + if (methodName == null) + continue; + + var declaringTypeName = method?.DeclaringType?.FullName; + if (declaringTypeName == null) + continue; + + if (!declaringTypeName.StartsWith(CodeAnalysisNamespace)) + continue; + + return declaringTypeName + "." + methodName; + } + } + } + catch + { + } + + // If we couldn't get a stack, do this + return exception.Message; + } + + private static LogLevel ConvertSeverity(ErrorSeverity severity) + => severity switch + { + ErrorSeverity.Uncategorized => LogLevel.None, + ErrorSeverity.Diagnostic => LogLevel.Debug, + ErrorSeverity.General => LogLevel.Information, + ErrorSeverity.Critical => LogLevel.Critical, + _ => LogLevel.None + }; + + private static FaultSeverity ConvertToFaultSeverity(LogLevel logLevel) + => logLevel switch + { + > LogLevel.Error => FaultSeverity.Critical, + > LogLevel.Information => FaultSeverity.General, + _ => FaultSeverity.Diagnostic + }; +} diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/package.json b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/package.json new file mode 100644 index 0000000000000..063e522014738 --- /dev/null +++ b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/package.json @@ -0,0 +1,4 @@ +{ + "name": "@microsoft/visualstudio-languageserver-internal", + "version": "0.0.1" +} \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index f4d277ae66993..333f7833b3f57 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -54,7 +54,7 @@ - + diff --git a/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj b/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj index 7406eb88551b7..d24eebbe46ad2 100644 --- a/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj +++ b/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj @@ -54,7 +54,6 @@ - From 72fb9bb76d4b6f769140a6c35814af1240f6db5f Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Wed, 5 Apr 2023 19:40:59 +0000 Subject: [PATCH 140/261] Merged PR 30400: Add Logger.SetLogger to initializer This sets it so the VSCode fault reporter also signs up to report telemetry that is sent through Logger.Log --- .../VSCodeTelemetryLogger.cs | 171 +++++++++++++++++- 1 file changed, 162 insertions(+), 9 deletions(-) diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs index 4c32ff2b0ae51..0525d4faafea0 100644 --- a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs +++ b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs @@ -8,6 +8,7 @@ using System.Composition; using System.Diagnostics; using System.Linq; +using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -22,7 +23,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Internal; [Export(typeof(ILspFaultLogger)), Shared] -internal class VSCodeWorkspaceTelemetryService : ILspFaultLogger +internal class VSCodeWorkspaceTelemetryService : ILspFaultLogger, ILogger { private TelemetrySession? _telemetrySession; private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; @@ -30,6 +31,8 @@ internal class VSCodeWorkspaceTelemetryService : ILspFaultLogger private static readonly ConcurrentDictionary s_eventMap = new(); private static readonly ConcurrentDictionary<(FunctionId id, string name), string> s_propertyMap = new(); + private readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); + private int _dumpsSubmitted = 0; [ImportingConstructor] @@ -45,6 +48,16 @@ public void Initialize() FatalError.Handler = (exception, severity, forceDump) => ReportFault(exception, ConvertSeverity(severity), forceDump); FatalError.CopyHandlerTo(typeof(Compilation).Assembly); + + var currentLogger = Logger.GetLogger(); + if (currentLogger is null) + { + Logger.SetLogger(this); + } + else + { + Logger.SetLogger(AggregateLogger.Create(currentLogger, this)); + } } public void ReportFault(Exception exception, LogLevel logLevel, bool forceDump) @@ -107,6 +120,84 @@ public void ReportFault(Exception exception, LogLevel logLevel, bool forceDump) } } + public bool IsEnabled(FunctionId functionId) + => _telemetrySession?.IsOptedIn ?? false; + + public void Log(FunctionId functionId, LogMessage logMessage) + { + var telemetryEvent = new TelemetryEvent(GetEventName(functionId)); + SetProperties(telemetryEvent, functionId, logMessage, delta: null); + + try + { + PostEvent(telemetryEvent); + } + catch + { + } + } + + public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int blockId, CancellationToken cancellationToken) + { + var eventName = GetEventName(functionId); + var kind = GetKind(logMessage); + + try + { + _pendingScopes[blockId] = Start(eventName, kind); + } + catch + { + } + } + + public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int blockId, int delta, CancellationToken cancellationToken) + { + Contract.ThrowIfFalse(_pendingScopes.TryRemove(blockId, out var scope)); + + var endEvent = GetEndEvent(scope); + SetProperties(endEvent, functionId, logMessage, delta); + + var result = cancellationToken.IsCancellationRequested ? TelemetryResult.UserCancel : TelemetryResult.Success; + + try + { + End(scope, result); + } + catch + { + } + } + + private object Start(string eventName, LogType type) + => type switch + { + LogType.Trace => _telemetrySession.StartOperation(eventName), + LogType.UserAction => _telemetrySession.StartUserTask(eventName), + _ => throw ExceptionUtilities.UnexpectedValue(type), + }; + + private static void End(object scope, TelemetryResult result) + { + if (scope is TelemetryScope operation) + operation.End(result); + else if (scope is TelemetryScope userTask) + userTask.End(result); + else + throw ExceptionUtilities.UnexpectedValue(scope); + } + + private static TelemetryEvent GetEndEvent(object scope) + => scope switch + { + TelemetryScope operation => operation.EndEvent, + TelemetryScope userTask => userTask.EndEvent, + _ => throw ExceptionUtilities.UnexpectedValue(scope) + }; + + private void PostEvent(TelemetryEvent telemetryEvent) + => _telemetrySession?.PostEvent(telemetryEvent); + private static string GetDescription(Exception exception) { const string CodeAnalysisNamespace = nameof(Microsoft) + "." + nameof(CodeAnalysis); @@ -148,15 +239,68 @@ private static string GetDescription(Exception exception) return exception.Message; } - private static LogLevel ConvertSeverity(ErrorSeverity severity) - => severity switch + private static void SetProperties(TelemetryEvent telemetryEvent, FunctionId functionId, LogMessage logMessage, int? delta) + { + if (logMessage is KeyValueLogMessage kvLogMessage) + { + AppendProperties(telemetryEvent, functionId, kvLogMessage); + } + else + { + var message = logMessage.GetMessage(); + if (!string.IsNullOrWhiteSpace(message)) + { + var propertyName = GetPropertyName(functionId, "Message"); + telemetryEvent.Properties.Add(propertyName, message); + } + } + + if (delta.HasValue) + { + var deltaPropertyName = GetPropertyName(functionId, "Delta"); + telemetryEvent.Properties.Add(deltaPropertyName, delta.Value); + } + } + + private static void AppendProperties(TelemetryEvent telemetryEvent, FunctionId functionId, KeyValueLogMessage logMessage) { - ErrorSeverity.Uncategorized => LogLevel.None, - ErrorSeverity.Diagnostic => LogLevel.Debug, - ErrorSeverity.General => LogLevel.Information, - ErrorSeverity.Critical => LogLevel.Critical, - _ => LogLevel.None - }; + foreach (var (name, value) in logMessage.Properties) + { + // call SetProperty. VS telemetry will take care of finding correct + // API based on given object type for us. + // + // numeric data will show up in ES with measurement prefix. + + telemetryEvent.Properties.Add(GetPropertyName(functionId, name), value switch + { + PiiValue pii => new TelemetryPiiProperty(pii.Value), + IEnumerable items => new TelemetryComplexProperty(items.Select(item => (item is PiiValue pii) ? new TelemetryPiiProperty(pii.Value) : item)), + _ => value + }); + } + } + + private const string EventPrefix = "vs/ide/vbcs/"; + private const string PropertyPrefix = "vs.ide.vbcs."; + + private static string GetEventName(FunctionId id) + => s_eventMap.GetOrAdd(id, id => EventPrefix + GetTelemetryName(id, separator: '/')); + + private static string GetPropertyName(FunctionId id, string name) + => s_propertyMap.GetOrAdd((id, name), key => PropertyPrefix + GetTelemetryName(id, separator: '.') + "." + key.name.ToLowerInvariant()); + + private static string GetTelemetryName(FunctionId id, char separator) + => Enum.GetName(typeof(FunctionId), id)!.Replace('_', separator).ToLowerInvariant(); + + private static LogLevel ConvertSeverity(ErrorSeverity severity) + => severity switch + { + ErrorSeverity.Uncategorized => LogLevel.None, + ErrorSeverity.Diagnostic => LogLevel.Debug, + ErrorSeverity.General => LogLevel.Information, + ErrorSeverity.Critical => LogLevel.Critical, + _ => LogLevel.None + }; private static FaultSeverity ConvertToFaultSeverity(LogLevel logLevel) => logLevel switch @@ -165,4 +309,13 @@ private static FaultSeverity ConvertToFaultSeverity(LogLevel logLevel) > LogLevel.Information => FaultSeverity.General, _ => FaultSeverity.Diagnostic }; + + private static LogType GetKind(LogMessage logMessage) + => logMessage is KeyValueLogMessage kvLogMessage + ? kvLogMessage.Kind + : logMessage.LogLevel switch + { + >= LogLevel.Information => LogType.UserAction, + _ => LogType.Trace + }; } From 45693826bf1f667cf01e4d18e200a1f9258f46f7 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 6 Apr 2023 07:12:49 +1000 Subject: [PATCH 141/261] Use real razor package version --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index a9fed347b4637..2b489177ab889 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -78,7 +78,7 @@ $(RefOnlyMicrosoftBuildPackagesVersion) 6.0.0-preview.0.15 17.2.31 - 7.0.6-dev + 17.6.0.2320501 4.3.0-1.final - 17.6.76-preview + 17.6.252 $(VisualStudioEditorPackagesVersion) 6.0.0-rtm.21518.12 6.0.0-rtm.21518.12 17.6.26-preview - 17.6.16-preview - 17.6.35295-preview.2 + 17.7.6-preview + 17.6.35829 16.10.0 4.1.0 7.0.0-alpha.1.22060.1 - 17.6.24-alpha + 17.6.40 17.4.0-preview-20220707-01 - 13.0.1 - 2.15.4-alpha + 13.0.3 + 2.15.26 4.3.0-1.final - 17.6.76-preview + 17.6.252 $(VisualStudioEditorPackagesVersion) 6.0.0-rtm.21518.12 6.0.0-rtm.21518.12 - 17.6.26-preview - 17.6.16-preview - 17.6.35295-preview.2 + 17.7.4-preview + 17.7.3-preview + 17.6.35829 16.10.0 4.1.0 7.0.0-alpha.1.22060.1 - 17.6.24-alpha + 17.6.40 17.4.0-preview-20220707-01 - 13.0.1 - 2.15.4-alpha + 13.0.3 + 2.15.26 + + + + + + + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e553c685503da..b5765e26d49a1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,16 +1,16 @@ - - https://github.com/dotnet/xliff-tasks - 7e80445ee82adbf9a8e6ae601ac5e239d982afaa - - - + https://github.com/dotnet/source-build-externals - ee790b0477953dd30ea83e0e47af909a04fd0ca3 + 33edde07d61cf7606d76ada765335fb81f1cbb71 + + https://github.com/dotnet/source-build-reference-packages + 01850f2b7bff23e118d1faecb941d770c8e626f2 + + @@ -18,6 +18,20 @@ b12f035e893c34ec2c965d75f6e21b7a2667e98d + + https://github.com/dotnet/xliff-tasks + b7fb98b199d0b1b6188da4f4bf4f5accddac98d4 + + + + https://github.com/dotnet/sourcelink + 3f43bf1b2dead2cb51f20dc47f6dfd7981248820 + + + + https://github.com/dotnet/symreader + 636a10b9d0aa317736c57d95f80e1c0849450715 + https://github.com/dotnet/roslyn 5d10d428050c0d6afef30a072c4ae68776621877 @@ -26,9 +40,9 @@ https://github.com/dotnet/arcade b12f035e893c34ec2c965d75f6e21b7a2667e98d - + https://github.com/dotnet/roslyn-analyzers - 801122692fc2953759f41330f5d42e9144a034ea + 19fb5cab215d2fe5d6c895d5f26c61dc1bdc0543 diff --git a/eng/Versions.props b/eng/Versions.props index d0a0acb03ddab..83e4f2a978c8b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -20,7 +20,7 @@ 3.3.5-beta1.23204.1 - 8.0.0-preview.23218.1 + 8.0.0-preview.23221.1 1.1.2-beta1.23163.2 0.1.149-beta @@ -118,8 +118,7 @@ 12.3.300-rc.3.83 1.0.0-beta3.21075.2 2.2.101 - 2.1.2 - 5.0.0 + 5.0.0 1.0.0 1.0.0 1.0.0 @@ -247,7 +246,7 @@ 4.3.0 5.0.0 7.0.0 - 5.0.0-preview.8.20407.11 + 7.0.0 4.5.5 7.0.0 6.0.0 diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index f62e0d476b2fd..51ba6cda8f794 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -2052,14 +2052,17 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Bind bool isUsedBeforeDeclaration(SimpleNameSyntax node, LocalSymbol localSymbol) { - Location localSymbolLocation = localSymbol.GetFirstLocation(); + if (!localSymbol.HasSourceLocation) + return false; - if (node.SyntaxTree == localSymbolLocation.SourceTree) - { - return node.SpanStart < localSymbolLocation.SourceSpan.Start; - } + var declarator = localSymbol.GetDeclaratorSyntax(); - return false; + // trivial position check, before more costly tree check (which requires walking up the nodes). Most + // code is correct, so this check is expected to succeed nearly every time. + if (node.SpanStart >= declarator.SpanStart) + return false; + + return node.SyntaxTree == declarator.SyntaxTree; } } diff --git a/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs b/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs index 03905c87e77ac..5d20d4fa4a07b 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs @@ -2300,6 +2300,8 @@ internal override SyntaxNode GetDeclaratorSyntax() throw new NotImplementedException(); } + internal override bool HasSourceLocation => false; + public override RefKind RefKind { get { return RefKind.None; } diff --git a/src/Compilers/CSharp/Portable/Errors/CSharpDiagnosticFormatter.cs b/src/Compilers/CSharp/Portable/Errors/CSharpDiagnosticFormatter.cs index 464ce1889ce43..e8ccce4fba389 100644 --- a/src/Compilers/CSharp/Portable/Errors/CSharpDiagnosticFormatter.cs +++ b/src/Compilers/CSharp/Portable/Errors/CSharpDiagnosticFormatter.cs @@ -11,5 +11,10 @@ internal CSharpDiagnosticFormatter() } public static new CSharpDiagnosticFormatter Instance { get; } = new CSharpDiagnosticFormatter(); + + internal override bool HasDefaultHelpLinkUri(Diagnostic diagnostic) + { + return diagnostic.Descriptor.HelpLinkUri == ErrorFacts.GetHelpLink((ErrorCode)diagnostic.Code); + } } } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index 3371188044f9a..f34b6e6c272a0 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -1170,7 +1170,7 @@ protected virtual void ReportUnassigned(Symbol symbol, SyntaxNode node, int slot if (skipIfUseBeforeDeclaration && symbol.Kind == SymbolKind.Local && - (symbol.Locations.Length == 0 || node.Span.End < symbol.GetFirstLocationOrNone().SourceSpan.Start)) + (symbol.TryGetFirstLocation() is var location && (location is null || node.Span.End < location.SourceSpan.Start))) { // We've already reported the use of a local before its declaration. No need to emit // another diagnostic for the same issue. diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.PlaceholderLocal.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.PlaceholderLocal.cs index 75b434c276c6f..766175d46fb59 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.PlaceholderLocal.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.PlaceholderLocal.cs @@ -61,6 +61,7 @@ public override bool Equals(Symbol obj, TypeCompareKind compareKind) internal override ConstantValue GetConstantValue(SyntaxNode node, LocalSymbol inProgress, BindingDiagnosticBag diagnostics = null) => null; internal override ImmutableBindingDiagnostic GetConstantValueDiagnostics(BoundExpression boundInitValue) => ImmutableBindingDiagnostic.Empty; internal override SyntaxNode GetDeclaratorSyntax() => throw ExceptionUtilities.Unreachable(); + internal override bool HasSourceLocation => false; internal override LocalSymbol WithSynthesizedLocalKindAndSyntax( SynthesizedLocalKind kind, SyntaxNode syntax #if DEBUG diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 37cd8e76abcd6..a65297ed6621f 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -85,9 +85,10 @@ internal enum TerminatorState IsEndOfFunctionPointerParameterListErrored = 1 << 24, IsEndOfFunctionPointerCallingConvention = 1 << 25, IsEndOfRecordOrClassOrStructOrInterfaceSignature = 1 << 26, + IsExpressionOrPatternInCaseLabelOfSwitchStatement = 1 << 27, } - private const int LastTerminatorState = (int)TerminatorState.IsEndOfRecordOrClassOrStructOrInterfaceSignature; + private const int LastTerminatorState = (int)TerminatorState.IsExpressionOrPatternInCaseLabelOfSwitchStatement; private bool IsTerminator() { @@ -6582,8 +6583,7 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy lastTokenOfType = this.EatToken(); result = ScanTypeFlags.NullableType; break; - case SyntaxKind.AsteriskToken - when lastTokenOfType.Kind != SyntaxKind.CloseBracketToken: // don't allow `Type[]*` + case SyntaxKind.AsteriskToken: // Check for pointer type(s) switch (mode) { @@ -6922,7 +6922,7 @@ bool canBeNullableType() return true; } - case SyntaxKind.AsteriskToken when type.Kind != SyntaxKind.ArrayType: + case SyntaxKind.AsteriskToken: switch (mode) { case ParseTypeMode.AfterIs: diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index e065a0f27b865..2fb24035996e9 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Roslyn.Utilities; @@ -50,6 +49,7 @@ private bool ConvertExpressionToType(ExpressionSyntax expression, [NotNullWhen(t return false; }; } + private PatternSyntax ParsePattern(Precedence precedence, bool afterIs = false, bool whenIsKeyword = false) { return ParseDisjunctivePattern(precedence, afterIs, whenIsKeyword); @@ -429,7 +429,10 @@ private bool IsValidPatternDesignation(bool whenIsKeyword) private CSharpSyntaxNode ParseExpressionOrPatternForSwitchStatement() { + var savedState = _termState; + _termState |= TerminatorState.IsExpressionOrPatternInCaseLabelOfSwitchStatement; var pattern = ParsePattern(Precedence.Conditional, whenIsKeyword: true); + _termState = savedState; return ConvertPatternToExpressionIfPossible(pattern); } @@ -536,6 +539,13 @@ SyntaxKind.GreaterThanToken or if (@this.CurrentToken.Kind is SyntaxKind.CloseParenToken or SyntaxKind.CloseBraceToken or SyntaxKind.CloseBracketToken or SyntaxKind.SemicolonToken) return PostSkipAction.Abort; + // `:` is usually treated as incorrect separation token. This helps for error recovery in basic typing scenarios like `{ Prop:$$ Prop1: { ... } }`. + // However, such behavior isn't much desirable when parsing pattern of a case label in a switch statement. For instance, consider the following example: `case { Prop: { }: case ...`. + // Normally we would skip second `:` and `case` keyword after it as bad tokens and continue parsing pattern, which produces a lot of noise errors. + // In order to avoid that and produce single error of missing `}` we exit on unexpected `:` in such cases. + if (@this._termState.HasFlag(TerminatorState.IsExpressionOrPatternInCaseLabelOfSwitchStatement) && @this.CurrentToken.Kind is SyntaxKind.ColonToken) + return PostSkipAction.Abort; + return @this.SkipBadSeparatedListTokensWithExpectedKind(ref open, list, static p => p.CurrentToken.Kind != SyntaxKind.CommaToken && !p.IsPossibleSubpatternElement(), static (p, closeKind) => p.CurrentToken.Kind == closeKind || p.CurrentToken.Kind == SyntaxKind.SemicolonToken, diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs b/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs index fb5e870c96ebc..090acf51b4863 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstantValueUtils.cs @@ -34,7 +34,7 @@ internal static class ConstantValueUtils BindingDiagnosticBag diagnostics) { var compilation = symbol.DeclaringCompilation; - var binderFactory = compilation.GetBinderFactory((SyntaxTree)symbol.GetFirstLocation().SourceTree); + var binderFactory = compilation.GetBinderFactory(equalsValueNode.SyntaxTree); var binder = binderFactory.GetBinder(equalsValueNode); binder = new WithPrimaryConstructorParametersBinder(symbol.ContainingType, binder); diff --git a/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs index 6b245b6162c3b..a81dd18bc7960 100644 --- a/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/LocalSymbol.cs @@ -273,7 +273,8 @@ public bool IsForEach } /// - /// Returns the syntax node that declares the variable. + /// Returns the syntax node that declares the variable. Should always return a value if returns . May throw if it returns . /// /// /// All user-defined and long-lived synthesized variables must return a reference to a node that is @@ -284,6 +285,12 @@ public bool IsForEach /// internal abstract SyntaxNode GetDeclaratorSyntax(); + /// + /// if this has a real syntax location in source code, otherwise. + /// A common example of a local without a source location is an EE local symbol. + /// + internal abstract bool HasSourceLocation { get; } + /// /// Describes whether this represents a modifiable variable. Note that /// this refers to the variable, not the underlying value, so if this diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs index 746a884447a8e..9c45f1e4ec3da 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs @@ -419,6 +419,8 @@ internal sealed override SyntaxNode GetDeclaratorSyntax() return _identifierToken.Parent; } + internal override bool HasSourceLocation => true; + public override ImmutableArray DeclaringSyntaxReferences { get diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 4c1e2a1942647..2fea136b5a89d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -1531,7 +1531,7 @@ internal override ImmutableArray GetEarlyAttributeDecodingMembers(string if (!membersAndInitializers.HaveIndexers) { - membersByName = membersAndInitializers.NonTypeMembers.ToDictionary(s => s.Name); + membersByName = membersAndInitializers.NonTypeMembers.ToDictionary(static s => s.Name); } else { @@ -1540,7 +1540,7 @@ internal override ImmutableArray GetEarlyAttributeDecodingMembers(string // IndexerNameAttribute). membersByName = membersAndInitializers.NonTypeMembers. WhereAsArray(s => !s.IsIndexer() && (!s.IsAccessor() || ((MethodSymbol)s).AssociatedSymbol?.IsIndexer() != true)). - ToDictionary(s => s.Name); + ToDictionary(static s => s.Name); } AddNestedTypesToDictionary(membersByName, GetTypeMembersDictionary()); @@ -2721,7 +2721,7 @@ private static bool ContainsModifier(SyntaxTokenList modifiers, SyntaxKind modif } else { - membersByName = membersAndInitializers.NonTypeMembers.ToDictionary(s => s.Name, StringOrdinalComparer.Instance); + membersByName = membersAndInitializers.NonTypeMembers.ToDictionary(static s => s.Name); // Merge types into the member dictionary AddNestedTypesToDictionary(membersByName, GetTypeMembersDictionary()); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs index 905d9a2f082dd..a8072e38d45d4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamespaceSymbol.cs @@ -314,13 +314,14 @@ internal override NamespaceExtent Extent // NOTE: a name maps into values collection containing types only instead of allocating another // NOTE: array of NamedTypeSymbol[] we downcast the array to ImmutableArray - var builder = new NameToSymbolMapBuilder(_mergedDeclaration.Children.Length); + var builder = new NameToSymbolMapBuilder(); foreach (var declaration in _mergedDeclaration.Children) { builder.Add(BuildSymbol(declaration, diagnostics)); } var result = builder.CreateMap(); + builder.Free(); CheckMembers(this, result, diagnostics); @@ -516,11 +517,15 @@ public override bool IsDefinedInSourceTree(SyntaxTree tree, TextSpan? definedWit private readonly struct NameToSymbolMapBuilder { - private readonly Dictionary _dictionary; + private readonly PooledDictionary _dictionary = PooledDictionary.GetInstance(); - public NameToSymbolMapBuilder(int capacity) + public NameToSymbolMapBuilder() { - _dictionary = new Dictionary(capacity, StringOrdinalComparer.Instance); + } + + public void Free() + { + _dictionary.Free(); } public void Add(NamespaceOrTypeSymbol symbol) @@ -546,7 +551,7 @@ public void Add(NamespaceOrTypeSymbol symbol) public Dictionary> CreateMap() { - var result = new Dictionary>(_dictionary.Count, StringOrdinalComparer.Instance); + var result = new Dictionary>(_dictionary.Count); foreach (var kvp in _dictionary) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedLocal.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedLocal.cs index 604f3b675b906..6499b709e10c1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedLocal.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedLocal.cs @@ -156,6 +156,9 @@ internal sealed override SyntaxNode GetDeclaratorSyntax() return _syntaxOpt; } + internal override bool HasSourceLocation + => _syntaxOpt != null; + public sealed override bool IsImplicitlyDeclared { get { return true; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs index a0cd6788629cd..22131b229323a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/TypeSubstitutedLocalSymbol.cs @@ -69,6 +69,9 @@ internal override SyntaxNode GetDeclaratorSyntax() return _originalVariable.GetDeclaratorSyntax(); } + internal override bool HasSourceLocation + => _originalVariable.HasSourceLocation; + public override ImmutableArray Locations { get { return _originalVariable.Locations; } diff --git a/src/Compilers/CSharp/Portable/Symbols/UpdatedContainingSymbolLocal.cs b/src/Compilers/CSharp/Portable/Symbols/UpdatedContainingSymbolLocal.cs index dc1292c702d08..ed02a75793f5f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/UpdatedContainingSymbolLocal.cs +++ b/src/Compilers/CSharp/Portable/Symbols/UpdatedContainingSymbolLocal.cs @@ -96,6 +96,8 @@ public override bool Equals(Symbol other, TypeCompareKind compareKind) _underlyingLocal.GetConstantValueDiagnostics(boundInitValue); internal override SyntaxNode GetDeclaratorSyntax() => _underlyingLocal.GetDeclaratorSyntax(); + internal override bool HasSourceLocation + => _underlyingLocal.HasSourceLocation; internal override LocalSymbol WithSynthesizedLocalKindAndSyntax( SynthesizedLocalKind kind, SyntaxNode syntax #if DEBUG diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs index 2bd370437e2c1..aa2d4ea5f0831 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedParameterSymbol.cs @@ -154,7 +154,7 @@ public override string GetDocumentationCommentXml(CultureInfo? preferredCulture internal sealed override ScopedKind EffectiveScope => _underlyingParameter.EffectiveScope; - internal override bool HasUnscopedRefAttribute => _underlyingParameter.HasUnscopedRefAttribute; + internal sealed override bool HasUnscopedRefAttribute => _underlyingParameter.HasUnscopedRefAttribute; internal sealed override bool UseUpdatedEscapeRules => _underlyingParameter.UseUpdatedEscapeRules; diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index cf28edcd5f19a..67a700515e295 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -3516,6 +3516,81 @@ public static void Main() itemSeparator: "\r\n"); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47310")] + public void DiagnosticFormatting_UrlFormat_ObsoleteAttribute() + { + var dir = Temp.CreateDirectory(); + var file = dir.CreateFile("a.cs"); + file.WriteAllText(""" + #pragma warning disable CS0436 // System.Obsolete conflict + #nullable enable + using System; + + var c1 = new C1(); + var c2 = new C2(); + var c3 = new C3(); + var c4 = new C4(); + + [Obsolete("Do not use C1", UrlFormat = "https://example.org/{0}")] + public class C1 { } + [Obsolete("Do not use C2", error: true, UrlFormat = "https://example.org/2/{0}")] + public class C2 { } + [Obsolete("Do not use C3", error: true, DiagnosticId = "OBSOLETEC3", UrlFormat = "https://example.org/3/{0}")] + public class C3 { } + [Obsolete("Do not use C4", DiagnosticId = "OBSOLETEC4", UrlFormat = "https://example.org/4")] + public class C4 { } + + namespace System + { + public class ObsoleteAttribute : Attribute + { + public ObsoleteAttribute() { } + public ObsoleteAttribute(string? message) { } + public ObsoleteAttribute(string? message, bool error) { } + + public string? DiagnosticId { get; set; } + public string? UrlFormat { get; set; } + } + } + """); + + var output = VerifyOutput(dir, file, + includeCurrentAssemblyAsAnalyzerReference: false, + expectedWarningCount: 2, + expectedErrorCount: 2, + additionalFlags: new[] { "/t:exe" }); + + AssertEx.Equal(""" + a.cs(5,14): warning CS0618: 'C1' is obsolete: 'Do not use C1' (https://example.org/CS0618) + a.cs(6,14): error CS0619: 'C2' is obsolete: 'Do not use C2' (https://example.org/2/CS0619) + a.cs(7,14): error OBSOLETEC3: 'C3' is obsolete: 'Do not use C3' (https://example.org/3/OBSOLETEC3) + a.cs(8,14): warning OBSOLETEC4: 'C4' is obsolete: 'Do not use C4' (https://example.org/4) + """, + output.Trim()); + + CleanupAllGeneratedFiles(file.Path); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47310")] + public void DiagnosticFormatting_DiagnosticAnalyzer() + { + var dir = Temp.CreateDirectory(); + var file = dir.CreateFile("a.cs"); + file.WriteAllText("class C { }"); + + var output = VerifyOutput(dir, file, + includeCurrentAssemblyAsAnalyzerReference: false, + expectedWarningCount: 1, + analyzers: new[] { new WarningWithUrlDiagnosticAnalyzer() }); + + AssertEx.Equal(""" + a.cs(1,7): warning Warning02: Throwing a diagnostic for types declared (https://example.org/analyzer) + """, + output.Trim()); + + CleanupAllGeneratedFiles(file.Path); + } + [WorkItem(540891, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540891")] [ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30289")] public void ParseOut() @@ -14712,6 +14787,23 @@ public override void CreateAnalyzerWithinCompilation(CompilationStartAnalysisCon } } + internal class WarningWithUrlDiagnosticAnalyzer : CompilationStartedAnalyzer + { + internal static readonly DiagnosticDescriptor Warning02 = new DiagnosticDescriptor("Warning02", "", "Throwing a diagnostic for types declared", "", DiagnosticSeverity.Warning, isEnabledByDefault: true, helpLinkUri: "https://example.org/analyzer"); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Warning02); + + public override void CreateAnalyzerWithinCompilation(CompilationStartAnalysisContext context) + { + context.RegisterSymbolAction( + static (symbolContext) => + { + symbolContext.ReportDiagnostic(Diagnostic.Create(Warning02, symbolContext.Symbol.Locations.First())); + }, + SymbolKind.NamedType); + } + } + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] internal class ErrorDiagnosticAnalyzer : CompilationStartedAnalyzer { diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/ManagedAddressTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/ManagedAddressTests.cs new file mode 100644 index 0000000000000..d0269fa467da2 --- /dev/null +++ b/src/Compilers/CSharp/Test/Emit2/Emit/ManagedAddressTests.cs @@ -0,0 +1,188 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Emit +{ + public class ManagedAddressTests : CSharpTestBase + { + [Fact] + public void TestPointerToArray() + { + var source = """ + using System; + + unsafe + { + var x = new[] { 0, 1, 2 }; + int[]* xp = &x; + var c = new C(xp); + c.Print(); + } + + public unsafe class C + { + private int[]* _x; + + public C(int[]* x) + { + _x = x; + } + + public void Print() + { + int[] x = *_x; + for (int i = 0; i < x.Length; i++) + { + Console.Write(x[i]); + } + } + } + """; + + var comp = CreateCompilation(source, options: TestOptions.UnsafeDebugExe).VerifyDiagnostics( + // (6,5): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('int[]') + // int[]* xp = &x; + Diagnostic(ErrorCode.WRN_ManagedAddr, "int[]*").WithArguments("int[]").WithLocation(6, 5), + // (6,17): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('int[]') + // int[]* xp = &x; + Diagnostic(ErrorCode.WRN_ManagedAddr, "&x").WithArguments("int[]").WithLocation(6, 17), + // (13,20): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('int[]') + // private int[]* _x; + Diagnostic(ErrorCode.WRN_ManagedAddr, "_x").WithArguments("int[]").WithLocation(13, 20), + // (15,21): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('int[]') + // public C(int[]* x) + Diagnostic(ErrorCode.WRN_ManagedAddr, "x").WithArguments("int[]").WithLocation(15, 21) + ); + var verifier = CompileAndVerify(comp, expectedOutput: "012", verify: Verification.Fails with + { + ILVerifyMessage = """ + [
$]: Expected numeric type on the stack. { Offset = 0x12, Found = address of 'int32[]' } + [.ctor]: Unmanaged pointers are not a verifiable type. { Offset = 0x9 } + [Print]: Expected ByRef on the stack. { Offset = 0x7, Found = Native Int } + """, + PEVerifyMessage = """ + [ : Program::
$][offset 0x00000012][found address of ref ] Expected numeric type on the stack. + [ : C::.ctor][offset 0x00000009] Unmanaged pointers are not a verifiable type. + [ : C::Print][offset 0x00000007][found unmanaged pointer] Expected ByRef on the stack. + """, + }); + + verifier.VerifyMethodBody("", """ + { + // Code size 36 (0x24) + .maxstack 4 + .locals init (int[] V_0, //x + int[]* V_1, //xp + C V_2) //c + // sequence point: { + IL_0000: nop + // sequence point: var x = new[] { 0, 1, 2 }; + IL_0001: ldc.i4.3 + IL_0002: newarr "int" + IL_0007: dup + IL_0008: ldc.i4.1 + IL_0009: ldc.i4.1 + IL_000a: stelem.i4 + IL_000b: dup + IL_000c: ldc.i4.2 + IL_000d: ldc.i4.2 + IL_000e: stelem.i4 + IL_000f: stloc.0 + // sequence point: int[]* xp = &x; + IL_0010: ldloca.s V_0 + IL_0012: conv.u + IL_0013: stloc.1 + // sequence point: var c = new C(xp); + IL_0014: ldloc.1 + IL_0015: newobj "C..ctor(int[]*)" + IL_001a: stloc.2 + // sequence point: c.Print(); + IL_001b: ldloc.2 + IL_001c: callvirt "void C.Print()" + IL_0021: nop + // sequence point: } + IL_0022: nop + IL_0023: ret + } + """); + + verifier.VerifyMethodBody("C..ctor", """ + { + // Code size 16 (0x10) + .maxstack 2 + // sequence point: public C(int[]* x) + IL_0000: ldarg.0 + IL_0001: call "object..ctor()" + IL_0006: nop + // sequence point: { + IL_0007: nop + // sequence point: _x = x; + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld "int[]* C._x" + // sequence point: } + IL_000f: ret + } + """); + + verifier.VerifyMethodBody("C.Print", """ + { + // Code size 39 (0x27) + .maxstack 2 + .locals init (int[] V_0, //x + int V_1, //i + bool V_2) + // sequence point: { + IL_0000: nop + // sequence point: int[] x = *_x; + IL_0001: ldarg.0 + IL_0002: ldfld "int[]* C._x" + IL_0007: ldind.ref + IL_0008: stloc.0 + // sequence point: int i = 0 + IL_0009: ldc.i4.0 + IL_000a: stloc.1 + // sequence point: + IL_000b: br.s IL_001c + // sequence point: { + IL_000d: nop + // sequence point: Console.Write(x[i]); + IL_000e: ldloc.0 + IL_000f: ldloc.1 + IL_0010: ldelem.i4 + IL_0011: call "void System.Console.Write(int)" + IL_0016: nop + // sequence point: } + IL_0017: nop + // sequence point: i++ + IL_0018: ldloc.1 + IL_0019: ldc.i4.1 + IL_001a: add + IL_001b: stloc.1 + // sequence point: i < x.Length + IL_001c: ldloc.1 + IL_001d: ldloc.0 + IL_001e: ldlen + IL_001f: conv.i4 + IL_0020: clt + IL_0022: stloc.2 + // sequence point: + IL_0023: ldloc.2 + IL_0024: brtrue.s IL_000d + // sequence point: } + IL_0026: ret + } + """); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 922e4f0151398..dae6fd47c58ab 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -3303,7 +3303,7 @@ public class C where T : System.TypedReference } [Fact] - public void ERR_ManagedAddr_ShallowRecursive() + public void WRN_ManagedAddr_ShallowRecursive() { var text = @" public unsafe struct S1 @@ -3325,7 +3325,7 @@ public unsafe struct S2 } [Fact] - public void ERR_ManagedAddr_DeepRecursive() + public void WRN_ManagedAddr_DeepRecursive() { var text = @" public unsafe struct A @@ -3357,7 +3357,7 @@ public struct C } [Fact] - public void ERR_ManagedAddr_Alias() + public void WRN_ManagedAddr_Alias() { var text = @" using Alias = S; @@ -3375,7 +3375,7 @@ public unsafe struct S } [Fact()] - public void ERR_ManagedAddr_Members() + public void WRN_ManagedAddr_Members() { var text = @" public unsafe struct S @@ -3413,6 +3413,21 @@ public unsafe struct S Diagnostic(ErrorCode.WRN_ManagedAddr, "p").WithArguments("S").WithLocation(10, 17)); } + [Fact] + public void WRN_ManagedAddr_ArrayPointer() + { + var text = @" +public unsafe struct S +{ + public int[]* s; +} +"; + CreateCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (4,19): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('int[]') + // public int[]* s; + Diagnostic(ErrorCode.WRN_ManagedAddr, "s").WithArguments("int[]").WithLocation(4, 19)); + } + [WorkItem(10195, "https://github.com/dotnet/roslyn/issues/10195")] [Fact] public void PointerToStructInPartialMethodSignature() diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs index 0ce1eb14cadff..e7d0e088e2699 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs @@ -1404,6 +1404,79 @@ public void NullableReturnTypeOrConditional_17() EOF(); } + [Fact] + public void NullablePointer() + { + UsingExpression("int?* () => default"); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ArrayPointer() + { + UsingExpression("int[]* () => default"); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.AsteriskToken); + } + + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + [Fact] public void NullableReturnTypeOrConditional_18() { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs index cbd4db8d3850a..29899976828fa 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs @@ -2155,32 +2155,20 @@ public void BrokenPattern_06() // (1,30): error CS0103: The name 'e' does not exist in the current context // class C { void M() { switch (e) { case (: ; } } } Diagnostic(ErrorCode.ERR_NameNotInContext, "e").WithArguments("e").WithLocation(1, 30), - // (1,35): error CS8070: Control cannot fall out of switch from final case label ('case (: ') + // (1,35): error CS8070: Control cannot fall out of switch from final case label ('case (:') // class C { void M() { switch (e) { case (: ; } } } - Diagnostic(ErrorCode.ERR_SwitchFallOut, "case (: ").WithArguments("case (: ").WithLocation(1, 35), + Diagnostic(ErrorCode.ERR_SwitchFallOut, "case (:").WithArguments("case (:").WithLocation(1, 35), // (1,40): error CS8370: Feature 'recursive patterns' is not available in C# 7.3. Please use language version 8.0 or greater. // class C { void M() { switch (e) { case (: ; } } } - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "(: ").WithArguments("recursive patterns", "8.0").WithLocation(1, 40), - // (1,41): error CS1001: Identifier expected + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "(").WithArguments("recursive patterns", "8.0").WithLocation(1, 40), + // (1,41): error CS1026: ) expected // class C { void M() { switch (e) { case (: ; } } } - Diagnostic(ErrorCode.ERR_IdentifierExpected, ":").WithLocation(1, 41), - // (1,43): error CS1026: ) expected - // class C { void M() { switch (e) { case (: ; } } } - Diagnostic(ErrorCode.ERR_CloseParenExpected, ";").WithLocation(1, 43), - // (1,43): error CS1003: Syntax error, ':' expected - // class C { void M() { switch (e) { case (: ; } } } - Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(":").WithLocation(1, 43)); + Diagnostic(ErrorCode.ERR_CloseParenExpected, ":").WithLocation(1, 41)); UsingStatement(test, TestOptions.RegularWithoutRecursivePatterns, - // (1,20): error CS1001: Identifier expected - // switch (e) { case (: ; } - Diagnostic(ErrorCode.ERR_IdentifierExpected, ":").WithLocation(1, 20), - // (1,22): error CS1026: ) expected - // switch (e) { case (: ; } - Diagnostic(ErrorCode.ERR_CloseParenExpected, ";").WithLocation(1, 22), - // (1,22): error CS1003: Syntax error, ':' expected + // (1,20): error CS1026: ) expected // switch (e) { case (: ; } - Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(":").WithLocation(1, 22)); + Diagnostic(ErrorCode.ERR_CloseParenExpected, ":").WithLocation(1, 20)); N(SyntaxKind.SwitchStatement); { N(SyntaxKind.SwitchKeyword); @@ -2204,7 +2192,7 @@ public void BrokenPattern_06() M(SyntaxKind.CloseParenToken); } } - M(SyntaxKind.ColonToken); + N(SyntaxKind.ColonToken); } N(SyntaxKind.EmptyStatement); { @@ -2737,25 +2725,16 @@ public void BrokenRecursivePattern01() Diagnostic(ErrorCode.ERR_NameNotInContext, "e").WithArguments("e").WithLocation(1, 30), // (1,40): error CS8370: Feature 'recursive patterns' is not available in C# 7.3. Please use language version 8.0 or greater. // class C { void M() { switch (e) { case T( : Q x = n; break; } } } - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "T( : Q x ").WithArguments("recursive patterns", "8.0").WithLocation(1, 40), + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "T( ").WithArguments("recursive patterns", "8.0").WithLocation(1, 40), // (1,40): error CS0246: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?) // class C { void M() { switch (e) { case T( : Q x = n; break; } } } Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "T").WithArguments("T").WithLocation(1, 40), - // (1,43): error CS1001: Identifier expected - // class C { void M() { switch (e) { case T( : Q x = n; break; } } } - Diagnostic(ErrorCode.ERR_IdentifierExpected, ":").WithLocation(1, 43), // (1,45): error CS0246: The type or namespace name 'Q' could not be found (are you missing a using directive or an assembly reference?) // class C { void M() { switch (e) { case T( : Q x = n; break; } } } Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Q").WithArguments("Q").WithLocation(1, 45), - // (1,49): error CS1026: ) expected - // class C { void M() { switch (e) { case T( : Q x = n; break; } } } - Diagnostic(ErrorCode.ERR_CloseParenExpected, "=").WithLocation(1, 49), - // (1,49): error CS1003: Syntax error, ':' expected - // class C { void M() { switch (e) { case T( : Q x = n; break; } } } - Diagnostic(ErrorCode.ERR_SyntaxError, "=").WithArguments(":").WithLocation(1, 49), - // (1,49): error CS1525: Invalid expression term '=' + // (1,43): error CS1026: ) expected // class C { void M() { switch (e) { case T( : Q x = n; break; } } } - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(1, 49), + Diagnostic(ErrorCode.ERR_CloseParenExpected, ":").WithLocation(1, 43), // (1,51): error CS0103: The name 'n' does not exist in the current context // class C { void M() { switch (e) { case T( : Q x = n; break; } } } Diagnostic(ErrorCode.ERR_NameNotInContext, "n").WithArguments("n").WithLocation(1, 51)); @@ -2763,21 +2742,9 @@ public void BrokenRecursivePattern01() // This put the parser into an infinite loop at one time. The precise diagnostics and nodes // are not as important as the fact that it terminates. UsingStatement(test, TestOptions.RegularWithoutRecursivePatterns, - // (1,22): error CS1001: Identifier expected - // switch (e) { case T( : Q x = n; break; } - Diagnostic(ErrorCode.ERR_IdentifierExpected, ":").WithLocation(1, 22), - // (1,28): error CS1003: Syntax error, ',' expected - // switch (e) { case T( : Q x = n; break; } - Diagnostic(ErrorCode.ERR_SyntaxError, "=").WithArguments(",").WithLocation(1, 28), - // (1,30): error CS1003: Syntax error, ',' expected - // switch (e) { case T( : Q x = n; break; } - Diagnostic(ErrorCode.ERR_SyntaxError, "n").WithArguments(",").WithLocation(1, 30), - // (1,31): error CS1026: ) expected - // switch (e) { case T( : Q x = n; break; } - Diagnostic(ErrorCode.ERR_CloseParenExpected, ";").WithLocation(1, 31), - // (1,31): error CS1003: Syntax error, ':' expected + // (1,22): error CS1026: ) expected // switch (e) { case T( : Q x = n; break; } - Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(":").WithLocation(1, 31) + Diagnostic(ErrorCode.ERR_CloseParenExpected, ":").WithLocation(1, 22) ); N(SyntaxKind.SwitchStatement); { @@ -2803,38 +2770,32 @@ public void BrokenRecursivePattern01() N(SyntaxKind.PositionalPatternClause); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Subpattern); - { - N(SyntaxKind.DeclarationPattern); - { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "Q"); - } - N(SyntaxKind.SingleVariableDesignation); - { - N(SyntaxKind.IdentifierToken, "x"); - } - } - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Subpattern); + M(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Q"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); { - N(SyntaxKind.ConstantPattern); + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "n"); - } + N(SyntaxKind.IdentifierToken, "n"); } } - M(SyntaxKind.CloseParenToken); } } - M(SyntaxKind.ColonToken); - } - N(SyntaxKind.EmptyStatement); - { N(SyntaxKind.SemicolonToken); } N(SyntaxKind.BreakStatement); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs index 91436d557a138..448aca9a97469 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs @@ -4178,37 +4178,64 @@ public void ParseCreateNullableTuple_02() [Fact] public void ParsePointerToArray() { - UsingStatement("int []* p;", - // (1,7): error CS1001: Identifier expected - // int []* p; - Diagnostic(ErrorCode.ERR_IdentifierExpected, "*").WithLocation(1, 7), - // (1,7): error CS1003: Syntax error, ',' expected - // int []* p; - Diagnostic(ErrorCode.ERR_SyntaxError, "*").WithArguments(",").WithLocation(1, 7) - ); + UsingStatement("int []* p;"); N(SyntaxKind.LocalDeclarationStatement); { N(SyntaxKind.VariableDeclaration); { - N(SyntaxKind.ArrayType); + N(SyntaxKind.PointerType); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.IntKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } } - N(SyntaxKind.ArrayRankSpecifier); + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "p"); + } + } + N(SyntaxKind.SemicolonToken); + } + EOF(); + } + + [Fact] + public void ParsePointerToNullableType() + { + UsingStatement("int?* p;"); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.NullableType); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.OmittedArraySizeExpression); + N(SyntaxKind.PredefinedType); { - N(SyntaxKind.OmittedArraySizeExpressionToken); + N(SyntaxKind.IntKeyword); } - N(SyntaxKind.CloseBracketToken); + N(SyntaxKind.QuestionToken); } + N(SyntaxKind.AsteriskToken); } - M(SyntaxKind.VariableDeclarator); + N(SyntaxKind.VariableDeclarator); { - M(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "p"); } } N(SyntaxKind.SemicolonToken); @@ -4737,6 +4764,640 @@ void M() EOF(); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67757")] + public void ParseSwitchStatementWithUnclosedRecursivePattern1() + { + UsingStatement(""" + switch (obj) + { + case Type { Prop: Type { }: + case Type { Prop: Type { }: + break; + } + """, + // (3,31): error CS1513: } expected + // case Type { Prop: Type { }: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(3, 31), + // (4,31): error CS1513: } expected + // case Type { Prop: Type { }: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(4, 31) + ); + N(SyntaxKind.SwitchStatement); + { + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "obj"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67757")] + public void ParseSwitchStatementWithUnclosedRecursivePattern2() + { + UsingStatement(""" + switch (obj) + { + case Type { Prop: Type {: + case Type { Prop: Type {: + break; + } + """, + // (3,29): error CS1513: } expected + // case Type { Prop: Type {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(3, 29), + // (3,29): error CS1513: } expected + // case Type { Prop: Type {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(3, 29), + // (4,29): error CS1513: } expected + // case Type { Prop: Type {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(4, 29), + // (4,29): error CS1513: } expected + // case Type { Prop: Type {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(4, 29) + ); + N(SyntaxKind.SwitchStatement); + { + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "obj"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67757")] + public void ParseSwitchStatementWithUnclosedRecursivePattern3() + { + UsingStatement(""" + switch (obj) + { + case { Prop: { Prop: {: + case { Prop: { Prop: {: + break; + } + """, + // (3,27): error CS1513: } expected + // case { Prop: { Prop: {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(3, 27), + // (3,27): error CS1513: } expected + // case { Prop: { Prop: {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(3, 27), + // (3,27): error CS1513: } expected + // case { Prop: { Prop: {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(3, 27), + // (4,27): error CS1513: } expected + // case { Prop: { Prop: {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(4, 27), + // (4,27): error CS1513: } expected + // case { Prop: { Prop: {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(4, 27), + // (4,27): error CS1513: } expected + // case { Prop: { Prop: {: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(4, 27) + ); + N(SyntaxKind.SwitchStatement); + { + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "obj"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67757")] + public void ParseSwitchStatementWithUnclosedListPattern1() + { + UsingStatement(""" + switch (obj) + { + case [: + case [: + break; + } + """, + // (3,11): error CS1003: Syntax error, ']' expected + // case [: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(3, 11), + // (4,11): error CS1003: Syntax error, ']' expected + // case [: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(4, 11) + ); + N(SyntaxKind.SwitchStatement); + { + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "obj"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67757")] + public void ParseSwitchStatementWithUnclosedListPattern2() + { + UsingStatement(""" + switch (obj) + { + case [[: + case [[: + break; + } + """, + // (3,12): error CS1003: Syntax error, ']' expected + // case [[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(3, 12), + // (3,12): error CS1003: Syntax error, ']' expected + // case [[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(3, 12), + // (4,12): error CS1003: Syntax error, ']' expected + // case [[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(4, 12), + // (4,12): error CS1003: Syntax error, ']' expected + // case [[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(4, 12) + ); + N(SyntaxKind.SwitchStatement); + { + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "obj"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67757")] + public void ParseSwitchStatementWithUnclosedListPattern3() + { + UsingStatement(""" + switch (obj) + { + case [[[: + case [[[: + break; + } + """, + // (3,13): error CS1003: Syntax error, ']' expected + // case [[[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(3, 13), + // (3,13): error CS1003: Syntax error, ']' expected + // case [[[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(3, 13), + // (3,13): error CS1003: Syntax error, ']' expected + // case [[[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(3, 13), + // (4,13): error CS1003: Syntax error, ']' expected + // case [[[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(4, 13), + // (4,13): error CS1003: Syntax error, ']' expected + // case [[[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(4, 13), + // (4,13): error CS1003: Syntax error, ']' expected + // case [[[: + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("]").WithLocation(4, 13) + ); + N(SyntaxKind.SwitchStatement); + { + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "obj"); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchSection); + { + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + M(SyntaxKind.CloseBracketToken); + } + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.CasePatternSwitchLabel); + { + N(SyntaxKind.CaseKeyword); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ListPattern); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.CloseBracketToken); + } + M(SyntaxKind.CloseBracketToken); + } + M(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.BreakStatement); + { + N(SyntaxKind.BreakKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + private sealed class TokenAndTriviaWalker : CSharpSyntaxWalker { public int Tokens; diff --git a/src/Compilers/Core/Portable/CodeAnalysisResources.resx b/src/Compilers/Core/Portable/CodeAnalysisResources.resx index 9404be8a58d91..6446105a28f97 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisResources.resx +++ b/src/Compilers/Core/Portable/CodeAnalysisResources.resx @@ -298,7 +298,7 @@ 'start' must not be negative - 'end' must not be less than 'start' + 'end' must not be less than 'start'. start='{0}' end='{1}'. Invalid content type diff --git a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs index e6e8f4bfdf8c6..8e614a6e6e722 100644 --- a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs @@ -832,14 +832,14 @@ public static int Sum(this ImmutableArray items, Func selector) return sum; } - internal static Dictionary> ToDictionary(this ImmutableArray items, Func keySelector, IEqualityComparer? comparer = null) + internal static Dictionary> ToDictionary(this ImmutableArray items, Func keySelector) where K : notnull where T : notnull { if (items.Length == 1) { T value = items[0]; - return new Dictionary>(1, comparer) + return new Dictionary>(1) { { keySelector(value), ImmutableArray.Create(value) }, }; @@ -847,7 +847,7 @@ public static int Sum(this ImmutableArray items, Func selector) if (items.Length == 0) { - return new Dictionary>(comparer); + return new Dictionary>(); } // bucketize @@ -856,7 +856,7 @@ public static int Sum(this ImmutableArray items, Func selector) // We store a mapping from keys to either a single item (very common in practice as this is used from // callers that maps names to symbols with that name, and most names are unique), or an array builder of items. - var accumulator = new Dictionary(items.Length, comparer); + var accumulator = PooledDictionary.GetInstance(); foreach (var item in items) { var key = keySelector(item); @@ -883,7 +883,7 @@ public static int Sum(this ImmutableArray items, Func selector) } } - var dictionary = new Dictionary>(accumulator.Count, comparer); + var dictionary = new Dictionary>(accumulator.Count); // freeze foreach (var pair in accumulator) @@ -893,6 +893,8 @@ public static int Sum(this ImmutableArray items, Func selector) : ImmutableArray.Create((T)pair.Value)); } + accumulator.Free(); + return dictionary; } diff --git a/src/Compilers/Core/Portable/Diagnostic/DiagnosticFormatter.cs b/src/Compilers/Core/Portable/Diagnostic/DiagnosticFormatter.cs index 6922eaa2f1fa8..8f3f0bd4bf6f7 100644 --- a/src/Compilers/Core/Portable/Diagnostic/DiagnosticFormatter.cs +++ b/src/Compilers/Core/Portable/Diagnostic/DiagnosticFormatter.cs @@ -53,16 +53,18 @@ public virtual string Format(Diagnostic diagnostic, IFormatProvider? formatter = basePath = null; } - return string.Format(formatter, "{0}{1}: {2}: {3}", + return string.Format(formatter, "{0}{1}: {2}: {3}{4}", FormatSourcePath(path, basePath, formatter), FormatSourceSpan(mappedSpan.Span, formatter), GetMessagePrefix(diagnostic), - diagnostic.GetMessage(culture)); + diagnostic.GetMessage(culture), + FormatHelpLinkUri(diagnostic)); default: - return string.Format(formatter, "{0}: {1}", + return string.Format(formatter, "{0}: {1}{2}", GetMessagePrefix(diagnostic), - diagnostic.GetMessage(culture)); + diagnostic.GetMessage(culture), + FormatHelpLinkUri(diagnostic)); } } @@ -101,6 +103,20 @@ internal string GetMessagePrefix(Diagnostic diagnostic) return string.Format("{0} {1}", prefix, diagnostic.Id); } + private string FormatHelpLinkUri(Diagnostic diagnostic) + { + var uri = diagnostic.Descriptor.HelpLinkUri; + + if (string.IsNullOrEmpty(uri) || HasDefaultHelpLinkUri(diagnostic)) + { + return string.Empty; + } + + return $" ({uri})"; + } + + internal virtual bool HasDefaultHelpLinkUri(Diagnostic diagnostic) => true; + internal static readonly DiagnosticFormatter Instance = new DiagnosticFormatter(); } } diff --git a/src/Compilers/Core/Portable/Text/LinePositionSpan.cs b/src/Compilers/Core/Portable/Text/LinePositionSpan.cs index d5bb6c64a2579..a2691b1ef80ea 100644 --- a/src/Compilers/Core/Portable/Text/LinePositionSpan.cs +++ b/src/Compilers/Core/Portable/Text/LinePositionSpan.cs @@ -30,7 +30,7 @@ public LinePositionSpan(LinePosition start, LinePosition end) { if (end < start) { - throw new ArgumentException(CodeAnalysisResources.EndMustNotBeLessThanStart, nameof(end)); + throw new ArgumentException(string.Format(CodeAnalysisResources.EndMustNotBeLessThanStart, start, end), nameof(end)); } _start = start; diff --git a/src/Compilers/Core/Portable/Text/TextSpan.cs b/src/Compilers/Core/Portable/Text/TextSpan.cs index 5374142e14982..b603ee71d937e 100644 --- a/src/Compilers/Core/Portable/Text/TextSpan.cs +++ b/src/Compilers/Core/Portable/Text/TextSpan.cs @@ -191,7 +191,7 @@ public static TextSpan FromBounds(int start, int end) if (end < start) { - throw new ArgumentOutOfRangeException(nameof(end), CodeAnalysisResources.EndMustNotBeLessThanStart); + throw new ArgumentOutOfRangeException(nameof(end), string.Format(CodeAnalysisResources.EndMustNotBeLessThanStart, start, end)); } return new TextSpan(start, end - start); diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf index fe35c80af403b..9d0e016965aeb 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf @@ -64,6 +64,11 @@ Funkce Upravit a pokračovat nemůže obnovit pozastavený iterátor, protože odpovídající příkaz yield return byl odstraněn. + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Generátor @@ -504,11 +509,6 @@ 'Začátek musí být záporný. - - 'end' must not be less than 'start' - 'Konec musí být míň než začátek. - - Invalid content type Neplatný typ obsahu diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf index 83317eef50105..9e3ddde826aaf 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.de.xlf @@ -64,6 +64,11 @@ "Bearbeiten und Fortfahren" kann den angehaltenen Iterator nicht fortsetzen, da die entsprechende yield return-Anweisung gelöscht wurde + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Generator @@ -504,11 +509,6 @@ 'Start' darf nicht negativ sein - - 'end' must not be less than 'start' - 'Ende' darf nicht kleiner sein als 'Start' - - Invalid content type Ungültiger Inhaltstyp diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf index 5435f4610a480..ce0c327c23abb 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.es.xlf @@ -64,6 +64,11 @@ Editar y continuar no puede reanudar el iterador suspendido porque se ha eliminado la instrucción yield return correspondiente + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Generador @@ -504,11 +509,6 @@ 'inicio' no puede ser negativo - - 'end' must not be less than 'start' - 'fin' no debe ser menor que 'inicio' - - Invalid content type Tipo de contenido no válido diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf index 97fcad39c32db..fd1fe740c4056 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.fr.xlf @@ -64,6 +64,11 @@ Modifier et continuer ne peut pas reprendre l’itérateur suspendu, car l’instruction yield return correspondante a été supprimée + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Générateur @@ -504,11 +509,6 @@ 'La valeur 'start' ne doit pas être négative - - 'end' must not be less than 'start' - 'La valeur 'end' ne doit pas être inférieure à la valeur 'start' - - Invalid content type Type de contenu non valide diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf index cfe73f6e9b140..b781ae931af58 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.it.xlf @@ -64,6 +64,11 @@ Modifica e Continua non sono in grado di riprendere l'enumeratore sospeso perché l'istruzione yield return corrispondente è stata eliminata + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Generatore @@ -504,11 +509,6 @@ 'start' non deve essere negativo - - 'end' must not be less than 'start' - 'il valore di 'end' deve essere minore di quello di 'start' - - Invalid content type Il tipo di contenuto non è valido diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf index 82e6f75550515..2ad78e41d4b8c 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf @@ -64,6 +64,11 @@ 対応する yield return ステートメントが削除されているため、エディット コンティニュは中断された反復子を再開できません + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator ジェネレーター @@ -504,11 +509,6 @@ 'start' は負の値であってはなりません - - 'end' must not be less than 'start' - 'end' は、'start' より小さい値であってはなりません - - Invalid content type 無効なコンテンツ タイプ diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf index fd9ea8406fa4d..b80b2057dd4a7 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ko.xlf @@ -64,6 +64,11 @@ 해당 yield return 문이 삭제되었으므로 편집하고 계속하기가 일시 중단된 반복기를 다시 시작할 수 없습니다. + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator 생성기 @@ -504,11 +509,6 @@ 'start'는 음수일 수 없습니다. - - 'end' must not be less than 'start' - 'end'는 'start'보다 커야 합니다. - - Invalid content type 잘못된 콘텐츠 형식입니다. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf index bb4432dd4ac1d..a32ad6b962d21 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pl.xlf @@ -64,6 +64,11 @@ Funkcja Edytuj i kontynuuj nie może wznowić wstrzymanego iteratora, ponieważ odpowiadająca jej instrukcja yield return została usunięta + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Generator @@ -504,11 +509,6 @@ 'Element „start” nie może być wartością ujemną - - 'end' must not be less than 'start' - 'Element „end” nie może mieć mniejszej wartości niż element „start” - - Invalid content type Nieprawidłowy typ zawartości diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf index 39af8c5344626..36f96123fd6d3 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf @@ -64,6 +64,11 @@ Editar e Continuar não pode retomar o iterador suspenso já que a instrução yield return correspondente foi excluída + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Gerador @@ -504,11 +509,6 @@ "início" não deve ser negativo - - 'end' must not be less than 'start' - "fim" não deve ser menor que "início" - - Invalid content type Tipo de conteúdo inválido diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf index 6a2303585b9c1..de0c0f0e66a48 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ru.xlf @@ -64,6 +64,11 @@ Операция "Изменить и продолжить" не может возобновить приостановленный итератор, поскольку соответствующий оператор yield return удален + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Генератор @@ -504,11 +509,6 @@ 'начальное значение не должно быть отрицательным - - 'end' must not be less than 'start' - 'конечное значение не должно быть меньше начального - - Invalid content type Недопустимый тип содержимого diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf index 2555197b552b5..d43068afa7d27 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.tr.xlf @@ -64,6 +64,11 @@ İlgili yield return deyimi silindiğinden Düzenle ve Devam Et, askıya alınmış yineleyiciyi sürdüremiyor + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator Oluşturucu @@ -504,11 +509,6 @@ 'start' negatif olmamalıdır - - 'end' must not be less than 'start' - 'end', 'start'tan az olmamalıdır - - Invalid content type Geçersiz içerik türü diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf index cfb977d37e009..31c530c691eb4 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hans.xlf @@ -64,6 +64,11 @@ 编辑并继续无法恢复挂起的迭代器,因为相应的 yield return 语句已被删除 + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator 生成器 @@ -504,11 +509,6 @@ '“开始”不能为负 - - 'end' must not be less than 'start' - '“结束时间”不得早于“开始时间” - - Invalid content type 无效的内容类型 diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf index f41fc5e9edd67..928098b9a22fa 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf @@ -64,6 +64,11 @@ 編輯和繼續無法繼續暫停的列舉程式,因為對應的 yield return 陳述式已刪除 + + 'end' must not be less than 'start'. start='{0}' end='{1}'. + 'end' must not be less than 'start'. start='{0}' end='{1}'. + + Generator 產生器 @@ -504,11 +509,6 @@ 'start' 不可為負值 - - 'end' must not be less than 'start' - 'end' 不可小於 'start' - - Invalid content type 內容類型無效 diff --git a/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj b/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj index 6cf90d717094f..9268709e34723 100644 --- a/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj +++ b/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj @@ -46,8 +46,11 @@ + + + diff --git a/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj b/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj index 2bac019b860be..853c5c22bb201 100644 --- a/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj +++ b/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj @@ -33,6 +33,7 @@ + diff --git a/src/Compilers/VisualBasic/Portable/Errors/DiagnosticFormatter.vb b/src/Compilers/VisualBasic/Portable/Errors/DiagnosticFormatter.vb index be70d54532ff1..b89f9f8c465fb 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/DiagnosticFormatter.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/DiagnosticFormatter.vb @@ -23,5 +23,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' Gets the current DiagnosticFormatter instance. '''
Public Shared Shadows ReadOnly Property Instance As New VisualBasicDiagnosticFormatter() + + Friend Overrides Function HasDefaultHelpLinkUri(diagnostic As Diagnostic) As Boolean + Return diagnostic.Descriptor.HelpLinkUri = ErrorFactory.GetHelpLink(CType(diagnostic.Code, ERRID)) + End Function End Class End Namespace diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 55181a155a1e1..b0e3b9affe360 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -7629,6 +7629,89 @@ C:\*.vb(100) : error BC30451: 'Goo' is not declared. It may be inaccessible due CleanupAllGeneratedFiles(file.Path) End Sub + + Public Sub DiagnosticFormatting_UrlFormat_ObsoleteAttribute() + Dim dir = Temp.CreateDirectory() + Dim file = dir.CreateFile("a.vb") + file.WriteAllText( + Public Class C1 + End Class + + + Public Class C2 + End Class + + + Public Class C3 + End Class + + + Public Class C4 + End Class +End Module + +Namespace System + Public Class ObsoleteAttribute + Inherits Attribute + + Public Sub New() + End Sub + + Public Sub New(ByVal message As String) + End Sub + + Public Sub New(ByVal message As String, ByVal [error] As Boolean) + End Sub + + Public Property DiagnosticId As String + Public Property UrlFormat As String + End Class +End Namespace +]]>.Value) + + Dim output = VerifyOutput(dir, file, + includeCurrentAssemblyAsAnalyzerReference:=False, + expectedWarningCount:=2, + expectedErrorCount:=2, + additionalFlags:={"/t:exe"}).Trim() + + Assert.Contains("warning BC40000: 'Program.C1' is obsolete: 'Do not use C1'. (https://example.org/BC40000)", output) + Assert.Contains("error BC30668: 'Program.C2' is obsolete: 'Do not use C2'. (https://example.org/2/BC30668)", output) + Assert.Contains("error OBSOLETEC3: 'Program.C3' is obsolete: 'Do not use C3'. (https://example.org/3/OBSOLETEC3)", output) + Assert.Contains("warning OBSOLETEC4: 'Program.C4' is obsolete: 'Do not use C4'. (https://example.org/4)", output) + + CleanupAllGeneratedFiles(file.Path) + End Sub + + + Public Sub DiagnosticFormatting_DiagnosticAnalyzer() + Dim dir = Temp.CreateDirectory() + Dim file = dir.CreateFile("a.vb") + file.WriteAllText(" +Class C +End Class +") + + Dim output = VerifyOutput(dir, file, + includeCurrentAssemblyAsAnalyzerReference:=False, + expectedWarningCount:=1, + analyzers:={New WarningWithUrlDiagnosticAnalyzer()}).Trim() + + Assert.Contains("warning Warning04: Throwing a diagnostic for types declared (https://example.org/analyzer)", output) + + CleanupAllGeneratedFiles(file.Path) + End Sub + Public Sub ParseFeatures() Dim args = DefaultParse({"/features:Test", "a.vb"}, _baseDirectory) @@ -10681,6 +10764,29 @@ End Class End Sub End Class + Friend Class WarningWithUrlDiagnosticAnalyzer + Inherits MockAbstractDiagnosticAnalyzer + + Friend Shared ReadOnly Warning04 As DiagnosticDescriptor = New DiagnosticDescriptor("Warning04", "", "Throwing a diagnostic for types declared", "", DiagnosticSeverity.Warning, isEnabledByDefault:=True, helpLinkUri:="https://example.org/analyzer") + + Public Overrides Sub CreateAnalyzerWithinCompilation(context As CompilationStartAnalysisContext) + context.RegisterSymbolAction(AddressOf AnalyzeSymbol, SymbolKind.NamedType) + End Sub + + Public Overrides Sub AnalyzeCompilation(context As CompilationAnalysisContext) + End Sub + + Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) + Get + Return ImmutableArray.Create(Warning04) + End Get + End Property + + Public Sub AnalyzeSymbol(context As SymbolAnalysisContext) + context.ReportDiagnostic(Diagnostic.Create(Warning04, context.Symbol.Locations.First())) + End Sub + End Class + Friend Class ErrorDiagnosticAnalyzer Inherits MockAbstractDiagnosticAnalyzer diff --git a/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs b/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs index da94baee92d68..df82f53ae1552 100644 --- a/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs +++ b/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs @@ -16,16 +16,12 @@ internal static class SegmentedArrayHelper // Large value types may benefit from a smaller number. internal const int IntrosortSizeThreshold = 16; - /// - /// A combination of and - /// . - /// - [SuppressMessage("Documentation", "CA1200:Avoid using cref tags with a prefix", Justification = "The field is not supported in all compilation targets.")] - internal const MethodImplOptions FastPathMethodImplOptions = MethodImplOptions.AggressiveInlining | (MethodImplOptions)512; - - [MethodImpl(FastPathMethodImplOptions)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetSegmentSize() { +#if NETCOREAPP3_0_OR_NEWER + return InlineCalculateSegmentSize(Unsafe.SizeOf()); +#else if (Unsafe.SizeOf() == Unsafe.SizeOf()) { return ReferenceTypeSegmentHelper.SegmentSize; @@ -34,11 +30,15 @@ internal static int GetSegmentSize() { return ValueTypeSegmentHelper.SegmentSize; } +#endif } - [MethodImpl(FastPathMethodImplOptions)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetSegmentShift() { +#if NETCOREAPP3_0_OR_NEWER + return InlineCalculateSegmentShift(Unsafe.SizeOf()); +#else if (Unsafe.SizeOf() == Unsafe.SizeOf()) { return ReferenceTypeSegmentHelper.SegmentShift; @@ -47,11 +47,15 @@ internal static int GetSegmentShift() { return ValueTypeSegmentHelper.SegmentShift; } +#endif } - [MethodImpl(FastPathMethodImplOptions)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetOffsetMask() { +#if NETCOREAPP3_0_OR_NEWER + return InlineCalculateOffsetMask(Unsafe.SizeOf()); +#else if (Unsafe.SizeOf() == Unsafe.SizeOf()) { return ReferenceTypeSegmentHelper.OffsetMask; @@ -60,6 +64,7 @@ internal static int GetOffsetMask() { return ValueTypeSegmentHelper.OffsetMask; } +#endif } /// @@ -121,6 +126,31 @@ private static int CalculateOffsetMask(int segmentSize) return segmentSize - 1; } + // Faster inline implementation for NETCOREAPP to avoid static constructors and non-inlineable + // generics with runtime lookups +#if NETCOREAPP3_0_OR_NEWER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateSegmentSize(int elementSize) + { + return 1 << InlineCalculateSegmentShift(elementSize); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateSegmentShift(int elementSize) + { + // Default Large Object Heap size threshold + // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 + const uint Threshold = 85000; + return System.Numerics.BitOperations.Log2((uint)((Threshold / elementSize) - (2 * Unsafe.SizeOf()))); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int InlineCalculateOffsetMask(int elementSize) + { + return InlineCalculateSegmentSize(elementSize) - 1; + } +#endif + internal static class TestAccessor { public static int CalculateSegmentSize(int elementSize) diff --git a/src/Dependencies/Collections/SegmentedArray`1.cs b/src/Dependencies/Collections/SegmentedArray`1.cs index 7805fea208ef3..9bb6c32dc5384 100644 --- a/src/Dependencies/Collections/SegmentedArray`1.cs +++ b/src/Dependencies/Collections/SegmentedArray`1.cs @@ -32,7 +32,6 @@ namespace Microsoft.CodeAnalysis.Collections /// private static int SegmentSize { - [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)] get { return SegmentedArrayHelper.GetSegmentSize(); @@ -44,7 +43,6 @@ private static int SegmentSize /// private static int SegmentShift { - [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)] get { return SegmentedArrayHelper.GetSegmentShift(); @@ -56,7 +54,6 @@ private static int SegmentShift /// private static int OffsetMask { - [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)] get { return SegmentedArrayHelper.GetOffsetMask(); @@ -115,7 +112,7 @@ private SegmentedArray(int length, T[][] items) public ref T this[int index] { - [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref _items[index >> SegmentShift][index & OffsetMask]; diff --git a/src/EditorFeatures/CSharpTest/CodeRefactorings/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs b/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeRefactorings/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs rename to src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewExceptionTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/PreviewExceptionTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewExceptionTests.cs rename to src/EditorFeatures/CSharpTest/CodeActions/PreviewExceptionTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/PreviewTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/Preview/PreviewTests.cs rename to src/EditorFeatures/CSharpTest/CodeActions/PreviewTests.cs diff --git a/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj b/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj index f8f4cfa81c9a8..85f1f7f2f290b 100644 --- a/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj +++ b/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj @@ -69,7 +69,12 @@ - + + + + + + diff --git a/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb b/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb index e7b172ddef693..957e2eb07f148 100644 --- a/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb +++ b/src/EditorFeatures/Test2/Simplification/BlockSimplificationTests.vb @@ -411,6 +411,169 @@ class Program return; } } + + + Await TestAsync(input, expected, DoNotPreferBraces) + End Function + + + Public Async Function TestCSharp_SimplifyBaseConstructorCall() As Task + Dim input = + + + + deps) { } +} +{|Simplify: +public partial class B : A +{ + public B() : base(default(Id), default(IEnumerable)) { } +} +|} +public partial class D { } +public partial class Id { } +public partial class V { } +]]> + + + + + Dim expected = + + deps) { } +} + +public partial class B : A +{ + public B() : base(default, default) { } +} + +public partial class D { } +public partial class Id { } +public partial class V { } +]]> + + + Await TestAsync(input, expected, DoNotPreferBraces) + End Function + + + Public Async Function TestCSharp_DoNotSimplifyBothArgumentsInAmbiguousBaseConstructorCall() As Task + Dim input = + + + + deps) { } + public A(string s, V v) { } +} +{|Simplify: +public partial class B : A +{ + public B() : base(default(Id), default(IEnumerable)) { } +} +|} +public partial class D { } +public partial class Id { } +public partial class V { } +]]> + + + + + Dim expected = + + deps) { } + public A(string s, V v) { } +} + +public partial class B : A +{ + public B() : base(default, default(IEnumerable)) { } +} + +public partial class D { } +public partial class Id { } +public partial class V { } +]]> + + + Await TestAsync(input, expected, DoNotPreferBraces) + End Function + + + Public Async Function TestCSharp_DoNotSimplifyBothArgumentsInAmbiguousCall() As Task + Dim input = + + + + deps) { } + public void Goo(string s, V v) { } +} +{|Simplify: +public partial class B : A +{ + public B() + { + Goo((Id)default, (IEnumerable)default); + } +} +|} +public partial class D { } +public partial class Id { } +public partial class V { } +]]> + + + + + Dim expected = + + deps) { } + public void Goo(string s, V v) { } +} + +public partial class B : A +{ + public B() + { + Goo(default, (IEnumerable)default); + } +} + +public partial class D { } +public partial class Id { } +public partial class V { } +]]> Await TestAsync(input, expected, DoNotPreferBraces) diff --git a/src/EditorFeatures/VisualBasicTest/CodeRefactorings/AddMissingImports/VisualBasicAddMissingImportsRefactoringProviderTests.vb b/src/EditorFeatures/VisualBasicTest/AddMissingImports/VisualBasicAddMissingImportsRefactoringProviderTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeRefactorings/AddMissingImports/VisualBasicAddMissingImportsRefactoringProviderTests.vb rename to src/EditorFeatures/VisualBasicTest/AddMissingImports/VisualBasicAddMissingImportsRefactoringProviderTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj b/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj index 479abc9b814b8..6d67a79e5b98a 100644 --- a/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj +++ b/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj @@ -71,6 +71,7 @@ + @@ -83,4 +84,8 @@ + + + + \ No newline at end of file diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EELocalSymbolBase.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EELocalSymbolBase.cs index 992deaa441e9b..5a49b8fc1b7c2 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EELocalSymbolBase.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EELocalSymbolBase.cs @@ -75,6 +75,8 @@ internal override SyntaxNode GetDeclaratorSyntax() throw ExceptionUtilities.Unreachable(); } + internal override bool HasSourceLocation => false; + internal sealed override UseSiteInfo GetUseSiteInfo() { var type = this.TypeWithAnnotations; diff --git a/src/EditorFeatures/CSharpTest/CodeActions/AddAwait/AddAwaitTests.cs b/src/Features/CSharpTest/AddAwait/AddAwaitTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/AddAwait/AddAwaitTests.cs rename to src/Features/CSharpTest/AddAwait/AddAwaitTests.cs diff --git a/src/EditorFeatures/CSharpTest/AddDebuggerDisplay/AddDebuggerDisplayTests.cs b/src/Features/CSharpTest/AddDebuggerDisplay/AddDebuggerDisplayTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddDebuggerDisplay/AddDebuggerDisplayTests.cs rename to src/Features/CSharpTest/AddDebuggerDisplay/AddDebuggerDisplayTests.cs diff --git a/src/EditorFeatures/CSharpTest/AddFileBanner/AddFileBannerTests.cs b/src/Features/CSharpTest/AddFileBanner/AddFileBannerTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddFileBanner/AddFileBannerTests.cs rename to src/Features/CSharpTest/AddFileBanner/AddFileBannerTests.cs diff --git a/src/EditorFeatures/CSharpTest/AddFileBanner/AddFileBannerTests_FixAll.cs b/src/Features/CSharpTest/AddFileBanner/AddFileBannerTests_FixAll.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddFileBanner/AddFileBannerTests_FixAll.cs rename to src/Features/CSharpTest/AddFileBanner/AddFileBannerTests_FixAll.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AbstractAddUsingTests.cs b/src/Features/CSharpTest/AddUsing/AbstractAddUsingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AbstractAddUsingTests.cs rename to src/Features/CSharpTest/AddUsing/AbstractAddUsingTests.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingNuGetTests.cs b/src/Features/CSharpTest/AddUsing/AddUsingNuGetTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AddUsingNuGetTests.cs rename to src/Features/CSharpTest/AddUsing/AddUsingNuGetTests.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests.cs b/src/Features/CSharpTest/AddUsing/AddUsingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests.cs rename to src/Features/CSharpTest/AddUsing/AddUsingTests.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTestsWithAddImportDiagnosticProvider.cs b/src/Features/CSharpTest/AddUsing/AddUsingTestsWithAddImportDiagnosticProvider.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AddUsingTestsWithAddImportDiagnosticProvider.cs rename to src/Features/CSharpTest/AddUsing/AddUsingTestsWithAddImportDiagnosticProvider.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_ExtensionMethods.cs b/src/Features/CSharpTest/AddUsing/AddUsingTests_ExtensionMethods.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_ExtensionMethods.cs rename to src/Features/CSharpTest/AddUsing/AddUsingTests_ExtensionMethods.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_Queries.cs b/src/Features/CSharpTest/AddUsing/AddUsingTests_Queries.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_Queries.cs rename to src/Features/CSharpTest/AddUsing/AddUsingTests_Queries.cs diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_Razor.cs b/src/Features/CSharpTest/AddUsing/AddUsingTests_Razor.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_Razor.cs rename to src/Features/CSharpTest/AddUsing/AddUsingTests_Razor.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/AbstractCSharpCodeActionTest.cs b/src/Features/CSharpTest/CodeActions/AbstractCSharpCodeActionTest.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/AbstractCSharpCodeActionTest.cs rename to src/Features/CSharpTest/CodeActions/AbstractCSharpCodeActionTest.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs b/src/Features/CSharpTest/CodeActions/ApplyChangesOperationTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ApplyChangesOperationTests.cs rename to src/Features/CSharpTest/CodeActions/ApplyChangesOperationTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/Preview/ErrorCases/ExceptionInCodeAction.cs b/src/Features/CSharpTest/CodeActions/Preview/ErrorCases/ExceptionInCodeAction.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/Preview/ErrorCases/ExceptionInCodeAction.cs rename to src/Features/CSharpTest/CodeActions/Preview/ErrorCases/ExceptionInCodeAction.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.cs b/src/Features/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.cs rename to src/Features/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.cs b/src/Features/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.cs rename to src/Features/CSharpTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs b/src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs rename to src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs b/src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs rename to src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimInterpolatedStringTests.cs b/src/Features/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimInterpolatedStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimInterpolatedStringTests.cs rename to src/Features/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimInterpolatedStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimStringTests.cs b/src/Features/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimStringTests.cs rename to src/Features/CSharpTest/ConvertBetweenRegularAndVerbatimString/ConvertBetweenRegularAndVerbatimStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs b/src/Features/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs rename to src/Features/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs b/src/Features/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs rename to src/Features/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertForEachToFor/ConvertForEachToForTests.cs b/src/Features/CSharpTest/ConvertForEachToFor/ConvertForEachToForTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertForEachToFor/ConvertForEachToForTests.cs rename to src/Features/CSharpTest/ConvertForEachToFor/ConvertForEachToForTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertForToForEach/ConvertForToForEachTests.cs b/src/Features/CSharpTest/ConvertForToForEach/ConvertForToForEachTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertForToForEach/ConvertForToForEachTests.cs rename to src/Features/CSharpTest/ConvertForToForEach/ConvertForToForEachTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.cs b/src/Features/CSharpTest/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.cs rename to src/Features/CSharpTest/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchTests.cs b/src/Features/CSharpTest/ConvertIfToSwitch/ConvertIfToSwitchTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchTests.cs rename to src/Features/CSharpTest/ConvertIfToSwitch/ConvertIfToSwitchTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertForEachToLinqQueryTests.cs b/src/Features/CSharpTest/ConvertLinq/ConvertForEachToLinqQueryTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertForEachToLinqQueryTests.cs rename to src/Features/CSharpTest/ConvertLinq/ConvertForEachToLinqQueryTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertLinqQueryToForEachTests.cs b/src/Features/CSharpTest/ConvertLinq/ConvertLinqQueryToForEachTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertLinqQueryToForEachTests.cs rename to src/Features/CSharpTest/ConvertLinq/ConvertLinqQueryToForEachTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs b/src/Features/CSharpTest/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs rename to src/Features/CSharpTest/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringFixAllTests.cs b/src/Features/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringFixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringFixAllTests.cs rename to src/Features/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringFixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs b/src/Features/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs rename to src/Features/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertNumericLiteral/ConvertNumericLiteralTests.cs b/src/Features/CSharpTest/ConvertNumericLiteral/ConvertNumericLiteralTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ConvertNumericLiteral/ConvertNumericLiteralTests.cs rename to src/Features/CSharpTest/ConvertNumericLiteral/ConvertNumericLiteralTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs b/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs rename to src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainRefactoringTests.cs b/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainRefactoringTests.cs rename to src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsAnalyzerTests.cs b/src/Features/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsAnalyzerTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsAnalyzerTests.cs rename to src/Features/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsAnalyzerTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsRefactoringTests.cs b/src/Features/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsRefactoringTests.cs rename to src/Features/CSharpTest/ConvertProgram/ConvertToTopLevelStatementsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs b/src/Features/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs rename to src/Features/CSharpTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.cs b/src/Features/CSharpTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.cs rename to src/Features/CSharpTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.cs b/src/Features/CSharpTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.cs rename to src/Features/CSharpTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertToRawString/ConvertRegularStringToRawStringTests.cs b/src/Features/CSharpTest/ConvertToRawString/ConvertRegularStringToRawStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertToRawString/ConvertRegularStringToRawStringTests.cs rename to src/Features/CSharpTest/ConvertToRawString/ConvertRegularStringToRawStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertToRawString/ConvertRegularStringToRawString_FixAllTests.cs b/src/Features/CSharpTest/ConvertToRawString/ConvertRegularStringToRawString_FixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertToRawString/ConvertRegularStringToRawString_FixAllTests.cs rename to src/Features/CSharpTest/ConvertToRawString/ConvertRegularStringToRawString_FixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs b/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs rename to src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs b/src/Features/CSharpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs rename to src/Features/CSharpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs diff --git a/src/EditorFeatures/CSharpTest/EmbeddedLanguages/JsonStringDetectorTests.cs b/src/Features/CSharpTest/EmbeddedLanguages/JsonStringDetectorTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/EmbeddedLanguages/JsonStringDetectorTests.cs rename to src/Features/CSharpTest/EmbeddedLanguages/JsonStringDetectorTests.cs diff --git a/src/EditorFeatures/CSharpTest/EmbeddedLanguages/ValidateJsonStringTests.cs b/src/Features/CSharpTest/EmbeddedLanguages/ValidateJsonStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/EmbeddedLanguages/ValidateJsonStringTests.cs rename to src/Features/CSharpTest/EmbeddedLanguages/ValidateJsonStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/EmbeddedLanguages/ValidateRegexStringTests.cs b/src/Features/CSharpTest/EmbeddedLanguages/ValidateRegexStringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/EmbeddedLanguages/ValidateRegexStringTests.cs rename to src/Features/CSharpTest/EmbeddedLanguages/ValidateRegexStringTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/EnableNullable/EnableNullableFixAllTests.cs b/src/Features/CSharpTest/EnableNullable/EnableNullableFixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/EnableNullable/EnableNullableFixAllTests.cs rename to src/Features/CSharpTest/EnableNullable/EnableNullableFixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/EnableNullable/EnableNullableTests.cs b/src/Features/CSharpTest/EnableNullable/EnableNullableTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/EnableNullable/EnableNullableTests.cs rename to src/Features/CSharpTest/EnableNullable/EnableNullableTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/EncapsulateField/EncapsulateFieldTests.cs b/src/Features/CSharpTest/EncapsulateField/EncapsulateFieldTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/EncapsulateField/EncapsulateFieldTests.cs rename to src/Features/CSharpTest/EncapsulateField/EncapsulateFieldTests.cs diff --git a/src/EditorFeatures/CSharpTest/ExtractClass/ExtractClassTests.cs b/src/Features/CSharpTest/ExtractClass/ExtractClassTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ExtractClass/ExtractClassTests.cs rename to src/Features/CSharpTest/ExtractClass/ExtractClassTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs b/src/Features/CSharpTest/ExtractMethod/ExtractLocalFunctionTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractLocalFunctionTests.cs rename to src/Features/CSharpTest/ExtractMethod/ExtractLocalFunctionTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs b/src/Features/CSharpTest/ExtractMethod/ExtractMethodTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs rename to src/Features/CSharpTest/ExtractMethod/ExtractMethodTests.cs diff --git a/src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyTests.cs b/src/Features/CSharpTest/FullyQualify/FullyQualifyTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyTests.cs rename to src/Features/CSharpTest/FullyQualify/FullyQualifyTests.cs diff --git a/src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyUnboundIdentifierTests.cs b/src/Features/CSharpTest/FullyQualify/FullyQualifyUnboundIdentifierTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyUnboundIdentifierTests.cs rename to src/Features/CSharpTest/FullyQualify/FullyQualifyUnboundIdentifierTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs b/src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs rename to src/Features/CSharpTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateConstructor/GenerateConstructorTests.cs b/src/Features/CSharpTest/GenerateConstructor/GenerateConstructorTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateConstructor/GenerateConstructorTests.cs rename to src/Features/CSharpTest/GenerateConstructor/GenerateConstructorTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.cs b/src/Features/CSharpTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.cs rename to src/Features/CSharpTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.cs b/src/Features/CSharpTest/GenerateEnumMember/GenerateEnumMemberTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.cs rename to src/Features/CSharpTest/GenerateEnumMember/GenerateEnumMemberTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs b/src/Features/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs rename to src/Features/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs b/src/Features/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs rename to src/Features/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs b/src/Features/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs rename to src/Features/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateConversionTests.cs b/src/Features/CSharpTest/GenerateMethod/GenerateConversionTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateConversionTests.cs rename to src/Features/CSharpTest/GenerateMethod/GenerateConversionTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateDeconstructMethodTests.cs b/src/Features/CSharpTest/GenerateMethod/GenerateDeconstructMethodTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateDeconstructMethodTests.cs rename to src/Features/CSharpTest/GenerateMethod/GenerateDeconstructMethodTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs b/src/Features/CSharpTest/GenerateMethod/GenerateMethodTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs rename to src/Features/CSharpTest/GenerateMethod/GenerateMethodTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs b/src/Features/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs rename to src/Features/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests.cs b/src/Features/CSharpTest/GenerateType/GenerateTypeTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests.cs rename to src/Features/CSharpTest/GenerateType/GenerateTypeTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests_Dialog.cs b/src/Features/CSharpTest/GenerateType/GenerateTypeTests_Dialog.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeTests_Dialog.cs rename to src/Features/CSharpTest/GenerateType/GenerateTypeTests_Dialog.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeWithUnboundAnalyzerTests.cs b/src/Features/CSharpTest/GenerateType/GenerateTypeWithUnboundAnalyzerTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/GenerateType/GenerateTypeWithUnboundAnalyzerTests.cs rename to src/Features/CSharpTest/GenerateType/GenerateTypeWithUnboundAnalyzerTests.cs diff --git a/src/EditorFeatures/CSharpTest/GenerateVariable/GenerateVariableTests.cs b/src/Features/CSharpTest/GenerateVariable/GenerateVariableTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/GenerateVariable/GenerateVariableTests.cs rename to src/Features/CSharpTest/GenerateVariable/GenerateVariableTests.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs rename to src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.cs b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.cs rename to src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs rename to src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementExplicitlyTests.cs b/src/Features/CSharpTest/ImplementInterface/ImplementExplicitlyTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementInterface/ImplementExplicitlyTests.cs rename to src/Features/CSharpTest/ImplementInterface/ImplementExplicitlyTests.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementImplicitlyTests.cs b/src/Features/CSharpTest/ImplementInterface/ImplementImplicitlyTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementInterface/ImplementImplicitlyTests.cs rename to src/Features/CSharpTest/ImplementInterface/ImplementImplicitlyTests.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/Features/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs rename to src/Features/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.cs b/src/Features/CSharpTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.cs rename to src/Features/CSharpTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/InitializeParameter/AddParameterCheckTests.cs b/src/Features/CSharpTest/InitializeParameter/AddParameterCheckTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InitializeParameter/AddParameterCheckTests.cs rename to src/Features/CSharpTest/InitializeParameter/AddParameterCheckTests.cs diff --git a/src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs b/src/Features/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs rename to src/Features/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs diff --git a/src/EditorFeatures/CSharpTest/InlineMethod/CSharpInlineMethodTests.cs b/src/Features/CSharpTest/InlineMethod/CSharpInlineMethodTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InlineMethod/CSharpInlineMethodTests.cs rename to src/Features/CSharpTest/InlineMethod/CSharpInlineMethodTests.cs diff --git a/src/EditorFeatures/CSharpTest/InlineMethod/CSharpInlineMethodTests_CrossLanguage.cs b/src/Features/CSharpTest/InlineMethod/CSharpInlineMethodTests_CrossLanguage.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InlineMethod/CSharpInlineMethodTests_CrossLanguage.cs rename to src/Features/CSharpTest/InlineMethod/CSharpInlineMethodTests_CrossLanguage.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs b/src/Features/CSharpTest/InlineTemporary/InlineTemporaryTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs rename to src/Features/CSharpTest/InlineTemporary/InlineTemporaryTests.cs diff --git a/src/EditorFeatures/CSharpTest/IntroduceParameter/IntroduceParameterTests.cs b/src/Features/CSharpTest/IntroduceParameter/IntroduceParameterTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/IntroduceParameter/IntroduceParameterTests.cs rename to src/Features/CSharpTest/IntroduceParameter/IntroduceParameterTests.cs diff --git a/src/EditorFeatures/CSharpTest/IntroduceUsingStatement/IntroduceUsingStatementTests.cs b/src/Features/CSharpTest/IntroduceUsingStatement/IntroduceUsingStatementTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/IntroduceUsingStatement/IntroduceUsingStatementTests.cs rename to src/Features/CSharpTest/IntroduceUsingStatement/IntroduceUsingStatementTests.cs diff --git a/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs b/src/Features/CSharpTest/IntroduceVariable/InteractiveIntroduceVariableTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs rename to src/Features/CSharpTest/IntroduceVariable/InteractiveIntroduceVariableTests.cs diff --git a/src/EditorFeatures/CSharpTest/IntroduceVariable/IntroduceLocalForExpressionTests.cs b/src/Features/CSharpTest/IntroduceVariable/IntroduceLocalForExpressionTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/IntroduceVariable/IntroduceLocalForExpressionTests.cs rename to src/Features/CSharpTest/IntroduceVariable/IntroduceLocalForExpressionTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/IntroduceVariable/IntroduceVariableTests.cs b/src/Features/CSharpTest/IntroduceVariable/IntroduceVariableTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/IntroduceVariable/IntroduceVariableTests.cs rename to src/Features/CSharpTest/IntroduceVariable/IntroduceVariableTests.cs diff --git a/src/EditorFeatures/CSharpTest/InvertConditional/InvertConditionalTests.cs b/src/Features/CSharpTest/InvertConditional/InvertConditionalTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InvertConditional/InvertConditionalTests.cs rename to src/Features/CSharpTest/InvertConditional/InvertConditionalTests.cs diff --git a/src/EditorFeatures/CSharpTest/InvertIf/InvertIfTests.Elseless.cs b/src/Features/CSharpTest/InvertIf/InvertIfTests.Elseless.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InvertIf/InvertIfTests.Elseless.cs rename to src/Features/CSharpTest/InvertIf/InvertIfTests.Elseless.cs diff --git a/src/EditorFeatures/CSharpTest/InvertIf/InvertIfTests.cs b/src/Features/CSharpTest/InvertIf/InvertIfTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InvertIf/InvertIfTests.cs rename to src/Features/CSharpTest/InvertIf/InvertIfTests.cs diff --git a/src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs b/src/Features/CSharpTest/InvertLogical/InvertLogicalTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/InvertLogical/InvertLogicalTests.cs rename to src/Features/CSharpTest/InvertLogical/InvertLogicalTests.cs diff --git a/src/EditorFeatures/CSharpTest/MakeLocalFunctionStatic/MakeLocalFunctionStaticRefactoringTests.cs b/src/Features/CSharpTest/MakeLocalFunctionStatic/MakeLocalFunctionStaticRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/MakeLocalFunctionStatic/MakeLocalFunctionStaticRefactoringTests.cs rename to src/Features/CSharpTest/MakeLocalFunctionStatic/MakeLocalFunctionStaticRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/MakeLocalFunctionStatic/PassInCapturedVariablesAsArgumentsCodeFixProviderTests.cs b/src/Features/CSharpTest/MakeLocalFunctionStatic/PassInCapturedVariablesAsArgumentsCodeFixProviderTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/MakeLocalFunctionStatic/PassInCapturedVariablesAsArgumentsCodeFixProviderTests.cs rename to src/Features/CSharpTest/MakeLocalFunctionStatic/PassInCapturedVariablesAsArgumentsCodeFixProviderTests.cs diff --git a/src/Features/CSharpTest/Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj b/src/Features/CSharpTest/Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj index a17d81dad1de6..b6570c7a73640 100644 --- a/src/Features/CSharpTest/Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj +++ b/src/Features/CSharpTest/Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj @@ -39,23 +39,6 @@ - - - - - - - - - - - - - - - - diff --git a/src/EditorFeatures/CSharpTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.cs b/src/Features/CSharpTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.cs rename to src/Features/CSharpTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.cs diff --git a/src/EditorFeatures/CSharpTest/MoveStaticMembers/CSharpMoveStaticMembersTests.cs b/src/Features/CSharpTest/MoveStaticMembers/CSharpMoveStaticMembersTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/MoveStaticMembers/CSharpMoveStaticMembersTests.cs rename to src/Features/CSharpTest/MoveStaticMembers/CSharpMoveStaticMembersTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/CSharpMoveTypeTestsBase.cs b/src/Features/CSharpTest/MoveType/CSharpMoveTypeTestsBase.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/MoveType/CSharpMoveTypeTestsBase.cs rename to src/Features/CSharpTest/MoveType/CSharpMoveTypeTestsBase.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.ActionCountTests.cs b/src/Features/CSharpTest/MoveType/MoveTypeTests.ActionCountTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.ActionCountTests.cs rename to src/Features/CSharpTest/MoveType/MoveTypeTests.ActionCountTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveScope.cs b/src/Features/CSharpTest/MoveType/MoveTypeTests.MoveScope.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveScope.cs rename to src/Features/CSharpTest/MoveType/MoveTypeTests.MoveScope.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs b/src/Features/CSharpTest/MoveType/MoveTypeTests.MoveToNewFile.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs rename to src/Features/CSharpTest/MoveType/MoveTypeTests.MoveToNewFile.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameFile.cs b/src/Features/CSharpTest/MoveType/MoveTypeTests.RenameFile.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameFile.cs rename to src/Features/CSharpTest/MoveType/MoveTypeTests.RenameFile.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameType.cs b/src/Features/CSharpTest/MoveType/MoveTypeTests.RenameType.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameType.cs rename to src/Features/CSharpTest/MoveType/MoveTypeTests.RenameType.cs diff --git a/src/EditorFeatures/CSharpTest/NameTupleElement/NameTupleElementTests.cs b/src/Features/CSharpTest/NameTupleElement/NameTupleElementTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/NameTupleElement/NameTupleElementTests.cs rename to src/Features/CSharpTest/NameTupleElement/NameTupleElementTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests.cs b/src/Features/CSharpTest/PreferFrameworkType/PreferFrameworkTypeTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests.cs rename to src/Features/CSharpTest/PreferFrameworkType/PreferFrameworkTypeTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.cs b/src/Features/CSharpTest/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.cs rename to src/Features/CSharpTest/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/PullMemberUp/CSharpPullMemberUpTests.cs b/src/Features/CSharpTest/PullMemberUp/CSharpPullMemberUpTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/PullMemberUp/CSharpPullMemberUpTests.cs rename to src/Features/CSharpTest/PullMemberUp/CSharpPullMemberUpTests.cs diff --git a/src/EditorFeatures/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs b/src/Features/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs rename to src/Features/CSharpTest/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_AsTests.cs diff --git a/src/EditorFeatures/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs b/src/Features/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs rename to src/Features/CSharpTest/RemoveUnusedVariable/RemoveUnusedVariableTests.cs diff --git a/src/EditorFeatures/CSharpTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.cs b/src/Features/CSharpTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.cs rename to src/Features/CSharpTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.cs diff --git a/src/EditorFeatures/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs b/src/Features/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs rename to src/Features/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs b/src/Features/CSharpTest/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs rename to src/Features/CSharpTest/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs b/src/Features/CSharpTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs rename to src/Features/CSharpTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs diff --git a/src/EditorFeatures/CSharpTest/ReverseForStatement/ReverseForStatementTests.cs b/src/Features/CSharpTest/ReverseForStatement/ReverseForStatementTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/ReverseForStatement/ReverseForStatementTests.cs rename to src/Features/CSharpTest/ReverseForStatement/ReverseForStatementTests.cs diff --git a/src/EditorFeatures/CSharpTest/SimplifyPropertyPattern/SimplifyPropertyPatternTests.cs b/src/Features/CSharpTest/SimplifyPropertyPattern/SimplifyPropertyPatternTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SimplifyPropertyPattern/SimplifyPropertyPatternTests.cs rename to src/Features/CSharpTest/SimplifyPropertyPattern/SimplifyPropertyPatternTests.cs diff --git a/src/EditorFeatures/CSharpTest/SimplifyThisOrMe/SimplifyThisOrMeTests.cs b/src/Features/CSharpTest/SimplifyThisOrMe/SimplifyThisOrMeTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SimplifyThisOrMe/SimplifyThisOrMeTests.cs rename to src/Features/CSharpTest/SimplifyThisOrMe/SimplifyThisOrMeTests.cs diff --git a/src/EditorFeatures/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs b/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs rename to src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs diff --git a/src/EditorFeatures/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs b/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs rename to src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/SpellCheck/SpellCheckTests.cs b/src/Features/CSharpTest/SpellCheck/SpellCheckTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Diagnostics/SpellCheck/SpellCheckTests.cs rename to src/Features/CSharpTest/SpellCheck/SpellCheckTests.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_Middle.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_Middle.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_Middle.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_Middle.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.cs diff --git a/src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.cs rename to src/Features/CSharpTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/CSharpSyncNamespaceTestsBase.cs b/src/Features/CSharpTest/SyncNamespace/CSharpSyncNamespaceTestsBase.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/CSharpSyncNamespaceTestsBase.cs rename to src/Features/CSharpTest/SyncNamespace/CSharpSyncNamespaceTestsBase.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs b/src/Features/CSharpTest/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs rename to src/Features/CSharpTest/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_MoveFile.cs b/src/Features/CSharpTest/SyncNamespace/SyncNamespaceTests_MoveFile.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_MoveFile.cs rename to src/Features/CSharpTest/SyncNamespace/SyncNamespaceTests_MoveFile.cs diff --git a/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_NoAction.cs b/src/Features/CSharpTest/SyncNamespace/SyncNamespaceTests_NoAction.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_NoAction.cs rename to src/Features/CSharpTest/SyncNamespace/SyncNamespaceTests_NoAction.cs diff --git a/src/EditorFeatures/CSharpTest/CodeRefactorings/UseExplicitOrImplicitType/UseExplicitTypeRefactoringTests.cs b/src/Features/CSharpTest/UseExplicitOrImplicitType/UseExplicitTypeRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeRefactorings/UseExplicitOrImplicitType/UseExplicitTypeRefactoringTests.cs rename to src/Features/CSharpTest/UseExplicitOrImplicitType/UseExplicitTypeRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeRefactorings/UseExplicitOrImplicitType/UseImplicitTypeRefactoringTests.cs b/src/Features/CSharpTest/UseExplicitOrImplicitType/UseImplicitTypeRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeRefactorings/UseExplicitOrImplicitType/UseImplicitTypeRefactoringTests.cs rename to src/Features/CSharpTest/UseExplicitOrImplicitType/UseImplicitTypeRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyFixAllTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyFixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyFixAllTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyFixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForAccessorsRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForAccessorsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForAccessorsRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForAccessorsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConstructorsRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConstructorsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConstructorsRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConstructorsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConversionOperatorsRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConversionOperatorsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConversionOperatorsRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForConversionOperatorsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForIndexersRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForIndexersRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForIndexersRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForIndexersRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForLocalFunctionsRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForLocalFunctionsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForLocalFunctionsRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForLocalFunctionsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForMethodsRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForMethodsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForMethodsRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForMethodsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForOperatorsRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForOperatorsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForOperatorsRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForOperatorsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForPropertiesRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForPropertiesRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForPropertiesRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBody/Refactoring/UseExpressionBodyForPropertiesRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBodyForLambda/UseExpressionBodyForLambdasRefactoringTests.cs b/src/Features/CSharpTest/UseExpressionBodyForLambda/UseExpressionBodyForLambdasRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseExpressionBodyForLambda/UseExpressionBodyForLambdasRefactoringTests.cs rename to src/Features/CSharpTest/UseExpressionBodyForLambda/UseExpressionBodyForLambdasRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseNamedArguments/UseNamedArgumentsTests.cs b/src/Features/CSharpTest/UseNamedArguments/UseNamedArgumentsTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseNamedArguments/UseNamedArgumentsTests.cs rename to src/Features/CSharpTest/UseNamedArguments/UseNamedArgumentsTests.cs diff --git a/src/EditorFeatures/CSharpTest/UseNameofInAttribute/UseNameofInAttributeTests.cs b/src/Features/CSharpTest/UseNameofInAttribute/UseNameofInAttributeTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UseNameofInAttribute/UseNameofInAttributeTests.cs rename to src/Features/CSharpTest/UseNameofInAttribute/UseNameofInAttributeTests.cs diff --git a/src/EditorFeatures/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs b/src/Features/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs rename to src/Features/CSharpTest/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzerTests.cs diff --git a/src/EditorFeatures/CSharpTest/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzerTests.cs b/src/Features/CSharpTest/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzerTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzerTests.cs rename to src/Features/CSharpTest/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzerTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeRefactorings/UseRecursivePatterns/UseRecursivePatternsRefactoringFixAllTests.cs b/src/Features/CSharpTest/UseRecursivePatterns/UseRecursivePatternsRefactoringFixAllTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeRefactorings/UseRecursivePatterns/UseRecursivePatternsRefactoringFixAllTests.cs rename to src/Features/CSharpTest/UseRecursivePatterns/UseRecursivePatternsRefactoringFixAllTests.cs diff --git a/src/EditorFeatures/CSharpTest/CodeRefactorings/UseRecursivePatterns/UseRecursivePatternsRefactoringTests.cs b/src/Features/CSharpTest/UseRecursivePatterns/UseRecursivePatternsRefactoringTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/CodeRefactorings/UseRecursivePatterns/UseRecursivePatternsRefactoringTests.cs rename to src/Features/CSharpTest/UseRecursivePatterns/UseRecursivePatternsRefactoringTests.cs diff --git a/src/EditorFeatures/CSharpTest/Utilities/CodeSnippets.cs b/src/Features/CSharpTest/Utilities/CodeSnippets.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Utilities/CodeSnippets.cs rename to src/Features/CSharpTest/Utilities/CodeSnippets.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/AbstractWrappingTests.cs b/src/Features/CSharpTest/Wrapping/AbstractWrappingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/AbstractWrappingTests.cs rename to src/Features/CSharpTest/Wrapping/AbstractWrappingTests.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/ArgumentWrappingTests.cs b/src/Features/CSharpTest/Wrapping/ArgumentWrappingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/ArgumentWrappingTests.cs rename to src/Features/CSharpTest/Wrapping/ArgumentWrappingTests.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/BinaryExpressionWrappingTests.cs b/src/Features/CSharpTest/Wrapping/BinaryExpressionWrappingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/BinaryExpressionWrappingTests.cs rename to src/Features/CSharpTest/Wrapping/BinaryExpressionWrappingTests.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/ChainedExpressionWrappingTests.cs b/src/Features/CSharpTest/Wrapping/ChainedExpressionWrappingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/ChainedExpressionWrappingTests.cs rename to src/Features/CSharpTest/Wrapping/ChainedExpressionWrappingTests.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/InitializerExpressionWrappingTests.cs b/src/Features/CSharpTest/Wrapping/InitializerExpressionWrappingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/InitializerExpressionWrappingTests.cs rename to src/Features/CSharpTest/Wrapping/InitializerExpressionWrappingTests.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/ParameterWrappingTests.cs b/src/Features/CSharpTest/Wrapping/ParameterWrappingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/ParameterWrappingTests.cs rename to src/Features/CSharpTest/Wrapping/ParameterWrappingTests.cs diff --git a/src/EditorFeatures/CSharpTest/Wrapping/SortingTests.cs b/src/Features/CSharpTest/Wrapping/SortingTests.cs similarity index 100% rename from src/EditorFeatures/CSharpTest/Wrapping/SortingTests.cs rename to src/Features/CSharpTest/Wrapping/SortingTests.cs diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticUpdateSource.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticUpdateSource.cs index f99e64a5b3760..0eb7971e96537 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticUpdateSource.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticUpdateSource.cs @@ -104,7 +104,7 @@ public void ReportDiagnostics(Workspace workspace, Solution solution, ImmutableA if (documentDiagnostics.Length > 0) { - foreach (var (documentId, diagnosticData) in documentDiagnostics.ToDictionary(data => data.DocumentId!)) + foreach (var (documentId, diagnosticData) in documentDiagnostics.ToDictionary(static data => data.DocumentId!)) { var diagnosticGroupId = (this, documentId); @@ -120,7 +120,7 @@ public void ReportDiagnostics(Workspace workspace, Solution solution, ImmutableA if (projectDiagnostics.Length > 0) { - foreach (var (projectId, diagnosticData) in projectDiagnostics.ToDictionary(data => data.ProjectId!)) + foreach (var (projectId, diagnosticData) in projectDiagnostics.ToDictionary(static data => data.ProjectId!)) { var diagnosticGroupId = (this, projectId); diff --git a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs index 2041505c5aa4c..b8807b349fda3 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs @@ -212,13 +212,27 @@ public static TextSpan RangeToTextSpan(LSP.Range range, SourceText text) try { - return text.Lines.GetTextSpan(linePositionSpan); + try + { + return text.Lines.GetTextSpan(linePositionSpan); + } + catch (ArgumentException) + { + // Create a custom error for this so we can examine the data we're getting. + throw new ArgumentException($"Range={RangeToString(range)}. text.Length={text.Length}. text.Lines.Count={text.Lines.Count}"); + } } // Temporary exception reporting to investigate https://github.com/dotnet/roslyn/issues/66258. catch (Exception e) when (FatalError.ReportAndPropagate(e)) { throw; } + + static string RangeToString(LSP.Range range) + => $"{{ Start={PositionToString(range.Start)}, End={PositionToString(range.End)} }}"; + + static string PositionToString(LSP.Position position) + => $"{{ Line={position.Line}, Character={position.Character} }}"; } public static LSP.TextEdit TextChangeToTextEdit(TextChange textChange, SourceText oldText) diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs index 067c35c239231..21021089de69a 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs @@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.PooledObjects; -using Microsoft.CodeAnalysis.Tags; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.UnifiedSuggestions; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -24,56 +23,133 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions internal static class CodeActionHelpers { /// - /// Get, order, and filter code actions, and then transform them into VSCodeActions. + /// Get, order, and filter code actions, and then transform them into VSCodeActions or CodeActions based on . /// /// /// Used by CodeActionsHandler. /// - public static async Task GetVSCodeActionsAsync( + public static async Task GetVSCodeActionsAsync( CodeActionParams request, Document document, CodeActionOptionsProvider fallbackOptions, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, + bool hasVsLspCapability, CancellationToken cancellationToken) { var actionSets = await GetActionSetsAsync( document, fallbackOptions, codeFixService, codeRefactoringService, request.Range, cancellationToken).ConfigureAwait(false); if (actionSets.IsDefaultOrEmpty) - return Array.Empty(); + return Array.Empty(); - var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + using var _ = ArrayBuilder.GetInstance(out var codeActions); + // VS-LSP support nested code action, but standard LSP doesn't. + if (hasVsLspCapability) + { + var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - // Each suggested action set should have a unique set number, which is used for grouping code actions together. - var currentHighestSetNumber = 0; + // Each suggested action set should have a unique set number, which is used for grouping code actions together. + var currentHighestSetNumber = 0; - using var _ = ArrayBuilder.GetInstance(out var codeActions); - foreach (var set in actionSets) + foreach (var set in actionSets) + { + var currentSetNumber = ++currentHighestSetNumber; + foreach (var suggestedAction in set.Actions) + { + if (!IsCodeActionNotSupportedByLSP(suggestedAction)) + { + codeActions.Add(GenerateVSCodeAction( + request, documentText, + suggestedAction: suggestedAction, + codeActionKind: GetCodeActionKindFromSuggestedActionCategoryName(set.CategoryName!), + setPriority: set.Priority, + applicableRange: set.ApplicableToSpan.HasValue ? ProtocolConversions.TextSpanToRange(set.ApplicableToSpan.Value, documentText) : null, + currentSetNumber: currentSetNumber, + currentHighestSetNumber: ref currentHighestSetNumber)); + } + } + } + } + else { - var currentSetNumber = ++currentHighestSetNumber; - foreach (var suggestedAction in set.Actions) + foreach (var set in actionSets) { - // Filter out code actions with options since they'll show dialogs and we can't remote the UI and the options. - if (suggestedAction.OriginalCodeAction is CodeActionWithOptions) - continue; + foreach (var suggestedAction in set.Actions) + { + if (!IsCodeActionNotSupportedByLSP(suggestedAction)) + { + codeActions.AddRange(GenerateCodeActions( + request, + suggestedAction, + GetCodeActionKindFromSuggestedActionCategoryName(set.CategoryName!))); + } + } + } + } - // Skip code actions that requires non-document changes. We can't apply them in LSP currently. - // https://github.com/dotnet/roslyn/issues/48698 - if (suggestedAction.OriginalCodeAction.Tags.Contains(CodeAction.RequiresNonDocumentChange)) - continue; + return codeActions.ToArray(); + } + + private static bool IsCodeActionNotSupportedByLSP(IUnifiedSuggestedAction suggestedAction) + // Filter out code actions with options since they'll show dialogs and we can't remote the UI and the options. + => suggestedAction.OriginalCodeAction is CodeActionWithOptions + // Skip code actions that requires non-document changes. We can't apply them in LSP currently. + // https://github.com/dotnet/roslyn/issues/48698 + || suggestedAction.OriginalCodeAction.Tags.Contains(CodeAction.RequiresNonDocumentChange); + + /// + /// Generate the matching code actions for . If it contains nested code actions, flatten them into an array. + /// + private static LSP.CodeAction[] GenerateCodeActions( + CodeActionParams request, + IUnifiedSuggestedAction suggestedAction, + LSP.CodeActionKind codeActionKind, + string currentTitle = "") + { + if (!string.IsNullOrEmpty(currentTitle)) + { + // Adding a delimiter for nested code actions, e.g. 'Suppress or Configure issues|Suppress IDEXXXX|in Source' + currentTitle += '|'; + } - codeActions.Add(GenerateVSCodeAction( - request, documentText, - suggestedAction: suggestedAction, - codeActionKind: GetCodeActionKindFromSuggestedActionCategoryName(set.CategoryName!), - setPriority: set.Priority, - applicableRange: set.ApplicableToSpan.HasValue ? ProtocolConversions.TextSpanToRange(set.ApplicableToSpan.Value, documentText) : null, - currentSetNumber: currentSetNumber, - currentHighestSetNumber: ref currentHighestSetNumber)); + var codeAction = suggestedAction.OriginalCodeAction; + currentTitle += codeAction.Title; + + var diagnosticsForFix = GetApplicableDiagnostics(request.Context, suggestedAction); + + using var _ = ArrayBuilder.GetInstance(out var builder); + if (suggestedAction is UnifiedSuggestedActionWithNestedActions unifiedSuggestedActions) + { + foreach (var actionSet in unifiedSuggestedActions.NestedActionSets) + { + foreach (var action in actionSet.Actions) + { + // Filter the configure and suppress fixer if it is not VS LSP, because it would generate many nested code actions. + // Tracking issue: https://github.com/microsoft/language-server-protocol/issues/994 + if (action.OriginalCodeAction is not AbstractConfigurationActionWithNestedActions) + { + builder.AddRange(GenerateCodeActions( + request, + action, + codeActionKind, + currentTitle)); + } + } } } + else + { + builder.Add(new LSP.CodeAction + { + // Change this to -> because it is shown to the user + Title = currentTitle.Replace("|", " -> "), + Kind = codeActionKind, + Diagnostics = diagnosticsForFix, + Data = new CodeActionResolveData(currentTitle, codeAction.CustomTags, request.Range, request.TextDocument) + }); + } - return codeActions.ToArray(); + return builder.ToArray(); } private static VSInternalCodeAction GenerateVSCodeAction( @@ -143,29 +219,29 @@ internal static class CodeActionHelpers return nestedActions.ToArray(); } + } - static LSP.Diagnostic[]? GetApplicableDiagnostics(LSP.CodeActionContext context, IUnifiedSuggestedAction action) + private static LSP.Diagnostic[]? GetApplicableDiagnostics(CodeActionContext context, IUnifiedSuggestedAction action) + { + if (action is UnifiedCodeFixSuggestedAction codeFixAction && context.Diagnostics != null) { - if (action is UnifiedCodeFixSuggestedAction codeFixAction && context.Diagnostics != null) + // Associate the diagnostics from the request that match the diagnostic fixed by the code action by ID. + // The request diagnostics are already restricted to the code fix location by the request. + var diagnosticCodesFixedByAction = codeFixAction.CodeFix.Diagnostics.Select(d => d.Id); + using var _ = ArrayBuilder.GetInstance(out var diagnosticsBuilder); + foreach (var requestDiagnostic in context.Diagnostics) { - // Associate the diagnostics from the request that match the diagnostic fixed by the code action by ID. - // The request diagnostics are already restricted to the code fix location by the request. - var diagnosticCodesFixedByAction = codeFixAction.CodeFix.Diagnostics.Select(d => d.Id); - using var _ = ArrayBuilder.GetInstance(out var diagnosticsBuilder); - foreach (var requestDiagnostic in context.Diagnostics) + var diagnosticCode = requestDiagnostic.Code?.Value?.ToString(); + if (diagnosticCodesFixedByAction.Contains(diagnosticCode)) { - var diagnosticCode = requestDiagnostic.Code?.Value?.ToString(); - if (diagnosticCodesFixedByAction.Contains(diagnosticCode)) - { - diagnosticsBuilder.Add(requestDiagnostic); - } + diagnosticsBuilder.Add(requestDiagnostic); } - - return diagnosticsBuilder.ToArray(); } - return null; + return diagnosticsBuilder.ToArray(); } + + return null; } /// diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionsHandler.cs index ab7eb0ea01bad..3a56b88cfe30c 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionsHandler.cs @@ -56,10 +56,10 @@ public async Task HandleRequestAsync(LSP.CodeActionParams requ Contract.ThrowIfNull(document); var options = _globalOptions.GetCodeActionOptionsProvider(); + var clientCapability = context.GetRequiredClientCapabilities(); var codeActions = await CodeActionHelpers.GetVSCodeActionsAsync( - request, document, options, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false); - + request, document, options, _codeFixService, _codeRefactoringService, hasVsLspCapability: clientCapability.HasVisualStudioLspCapability(), cancellationToken).ConfigureAwait(false); return codeActions; } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs index 6f4fba6c1130b..30442ca82cd44 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/CodeActionsTests.cs @@ -5,23 +5,14 @@ #nullable disable using System; -using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.AddImport; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; -using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; -using Microsoft.CodeAnalysis.Shared.TestHooks; -using Microsoft.CodeAnalysis.SolutionCrawler; -using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Roslyn.Test.Utilities; using Xunit; @@ -47,7 +38,7 @@ void M() {|caret:|}int i = 1; } }"; - await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace); + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, initializationOptions: new InitializationOptions() { ClientCapabilities = new VSInternalClientCapabilities { SupportsVisualStudioExtensions = true } }); var caretLocation = testLspServer.GetLocations("caret").Single(); var expected = CreateCodeAction( @@ -145,6 +136,76 @@ void M() Assert.Equal(AddImportDiagnosticIds.CS0103, addImport.Diagnostics.Single().Code.Value); } + [WpfTheory, CombinatorialData] + public async Task TestNoSuppressionFixerInStandardLSP(bool mutatingLspWorkspace) + { + var markup = @" +class ABC +{ + private static async void {|caret:XYZ|}() + { + } +}"; + + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace); + + var caret = testLspServer.GetLocations("caret").Single(); + var codeActionParams = new LSP.CodeActionParams + { + TextDocument = CreateTextDocumentIdentifier(caret.Uri), + Range = caret.Range, + Context = new LSP.CodeActionContext + { + Diagnostics = new[] + { + new LSP.Diagnostic + { + // async method lack of await. + Code = "CS1998" + } + } + } + }; + + var results = await RunGetCodeActionsAsync(testLspServer, codeActionParams); + Assert.Single(results); + Assert.Equal("Make method synchronous", results[0].Title); + } + + [WpfTheory, CombinatorialData] + public async Task TestStandardLspNestedCodeAction(bool mutatingLspWorkspace) + { + var markup = @" +class ABC +{ + private void XYZ() + { + var a = {|caret:A()|}; + } + + private int A() => 1; +}"; + + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace); + + var caret = testLspServer.GetLocations("caret").Single(); + var codeActionParams = new LSP.CodeActionParams + { + TextDocument = CreateTextDocumentIdentifier(caret.Uri), + Range = caret.Range, + Context = new LSP.CodeActionContext + { + } + }; + + var results = await RunGetCodeActionsAsync(testLspServer, codeActionParams); + var resultsTitles = results.Select(r => r.Title).ToArray(); + // Inline method refactoring provide nested code actions. + // Make sure it is correctly displayed. + Assert.True(resultsTitles.Contains("Inline 'A()' -> Inline 'A()'")); + Assert.True(resultsTitles.Contains("Inline 'A()' -> Inline and keep 'A()'")); + } + private static async Task RunGetCodeActionsAsync( TestLspServer testLspServer, CodeActionParams codeActionParams) diff --git a/src/Features/Test/Microsoft.CodeAnalysis.Features.UnitTests.csproj b/src/Features/Test/Microsoft.CodeAnalysis.Features.UnitTests.csproj index a08745012eb5c..e0253a29743dc 100644 --- a/src/Features/Test/Microsoft.CodeAnalysis.Features.UnitTests.csproj +++ b/src/Features/Test/Microsoft.CodeAnalysis.Features.UnitTests.csproj @@ -44,23 +44,6 @@ - - - - - - - - - - - - - - - - diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/AddAwait/AddAwaitTests.vb b/src/Features/VisualBasicTest/AddAwait/AddAwaitTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/AddAwait/AddAwaitTests.vb rename to src/Features/VisualBasicTest/AddAwait/AddAwaitTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.vb b/src/Features/VisualBasicTest/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.vb rename to src/Features/VisualBasicTest/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/AddDebuggerDisplay/AddDebuggerDisplayTests.vb b/src/Features/VisualBasicTest/AddDebuggerDisplay/AddDebuggerDisplayTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/AddDebuggerDisplay/AddDebuggerDisplayTests.vb rename to src/Features/VisualBasicTest/AddDebuggerDisplay/AddDebuggerDisplayTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/AddFileBanner/AddFileBannerTests.vb b/src/Features/VisualBasicTest/AddFileBanner/AddFileBannerTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/AddFileBanner/AddFileBannerTests.vb rename to src/Features/VisualBasicTest/AddFileBanner/AddFileBannerTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AbstractAddImportTests.vb b/src/Features/VisualBasicTest/AddImport/AbstractAddImportTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AbstractAddImportTests.vb rename to src/Features/VisualBasicTest/AddImport/AbstractAddImportTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests.vb b/src/Features/VisualBasicTest/AddImport/AddImportTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests.vb rename to src/Features/VisualBasicTest/AddImport/AddImportTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTestsWithAddImportDiagnosticProvider.vb b/src/Features/VisualBasicTest/AddImport/AddImportTestsWithAddImportDiagnosticProvider.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTestsWithAddImportDiagnosticProvider.vb rename to src/Features/VisualBasicTest/AddImport/AddImportTestsWithAddImportDiagnosticProvider.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb b/src/Features/VisualBasicTest/AddImport/AddImportTests_NuGet.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb rename to src/Features/VisualBasicTest/AddImport/AddImportTests_NuGet.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/AbstractVisualBasicCodeActionTest.vb b/src/Features/VisualBasicTest/CodeActions/AbstractVisualBasicCodeActionTest.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/AbstractVisualBasicCodeActionTest.vb rename to src/Features/VisualBasicTest/CodeActions/AbstractVisualBasicCodeActionTest.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.vb b/src/Features/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.vb rename to src/Features/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToClassTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.vb b/src/Features/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.vb rename to src/Features/VisualBasicTest/ConvertAnonymousType/ConvertAnonymousTypeToTupleTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.vb b/src/Features/VisualBasicTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.vb rename to src/Features/VisualBasicTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertCast/ConvertDirectCastToTryCastTests.vb b/src/Features/VisualBasicTest/ConvertCast/ConvertDirectCastToTryCastTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertCast/ConvertDirectCastToTryCastTests.vb rename to src/Features/VisualBasicTest/ConvertCast/ConvertDirectCastToTryCastTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertCast/ConvertTryCastToDirectCastTests.vb b/src/Features/VisualBasicTest/ConvertCast/ConvertTryCastToDirectCastTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertCast/ConvertTryCastToDirectCastTests.vb rename to src/Features/VisualBasicTest/ConvertCast/ConvertTryCastToDirectCastTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertForEachToFor/ConvertForEachToForTests.vb b/src/Features/VisualBasicTest/ConvertForEachToFor/ConvertForEachToForTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertForEachToFor/ConvertForEachToForTests.vb rename to src/Features/VisualBasicTest/ConvertForEachToFor/ConvertForEachToForTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertForToForEach/ConvertForToForEachTests.vb b/src/Features/VisualBasicTest/ConvertForToForEach/ConvertForToForEachTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertForToForEach/ConvertForToForEachTests.vb rename to src/Features/VisualBasicTest/ConvertForToForEach/ConvertForToForEachTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.vb b/src/Features/VisualBasicTest/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.vb rename to src/Features/VisualBasicTest/ConvertIfToSwitch/ConvertIfToSwitchFixAllTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchTests.vb b/src/Features/VisualBasicTest/ConvertIfToSwitch/ConvertIfToSwitchTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/ConvertIfToSwitch/ConvertIfToSwitchTests.vb rename to src/Features/VisualBasicTest/ConvertIfToSwitch/ConvertIfToSwitchTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ConvertNumericLiteral/ConvertNumericLiteralTests.vb b/src/Features/VisualBasicTest/ConvertNumericLiteral/ConvertNumericLiteralTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/ConvertNumericLiteral/ConvertNumericLiteralTests.vb rename to src/Features/VisualBasicTest/ConvertNumericLiteral/ConvertNumericLiteralTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb b/src/Features/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb rename to src/Features/VisualBasicTest/ConvertToInterpolatedString/ConvertConcatenationToInterpolatedStringTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.vb b/src/Features/VisualBasicTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.vb rename to src/Features/VisualBasicTest/ConvertToInterpolatedString/ConvertPlaceholderToInterpolatedStringTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.vb b/src/Features/VisualBasicTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.vb rename to src/Features/VisualBasicTest/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb b/src/Features/VisualBasicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb rename to src/Features/VisualBasicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/CorrectNextControlVariable/CorrectNextControlVariableTests.vb b/src/Features/VisualBasicTest/CorrectNextControlVariable/CorrectNextControlVariableTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/CorrectNextControlVariable/CorrectNextControlVariableTests.vb rename to src/Features/VisualBasicTest/CorrectNextControlVariable/CorrectNextControlVariableTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/EmbeddedLanguages/ValidateJsonStringTests.vb b/src/Features/VisualBasicTest/EmbeddedLanguages/ValidateJsonStringTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/EmbeddedLanguages/ValidateJsonStringTests.vb rename to src/Features/VisualBasicTest/EmbeddedLanguages/ValidateJsonStringTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/EmbeddedLanguages/ValidateRegexStringTests.vb b/src/Features/VisualBasicTest/EmbeddedLanguages/ValidateRegexStringTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/EmbeddedLanguages/ValidateRegexStringTests.vb rename to src/Features/VisualBasicTest/EmbeddedLanguages/ValidateRegexStringTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/EncapsulateField/EncapsulateFieldTests.vb b/src/Features/VisualBasicTest/EncapsulateField/EncapsulateFieldTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/EncapsulateField/EncapsulateFieldTests.vb rename to src/Features/VisualBasicTest/EncapsulateField/EncapsulateFieldTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/ExitContinue/ExitContinueCodeActionTests.vb b/src/Features/VisualBasicTest/ExitContinue/ExitContinueCodeActionTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/ExitContinue/ExitContinueCodeActionTests.vb rename to src/Features/VisualBasicTest/ExitContinue/ExitContinueCodeActionTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb b/src/Features/VisualBasicTest/ExtractMethod/ExtractMethodTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/ExtractMethod/ExtractMethodTests.vb rename to src/Features/VisualBasicTest/ExtractMethod/ExtractMethodTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/FixIncorrectFunctionReturnType/FixIncorrectFunctionReturnTypeTests.vb b/src/Features/VisualBasicTest/FixIncorrectFunctionReturnType/FixIncorrectFunctionReturnTypeTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/FixIncorrectFunctionReturnType/FixIncorrectFunctionReturnTypeTests.vb rename to src/Features/VisualBasicTest/FixIncorrectFunctionReturnType/FixIncorrectFunctionReturnTypeTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/FullyQualify/FullyQualifyTests.vb b/src/Features/VisualBasicTest/FullyQualify/FullyQualifyTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/FullyQualify/FullyQualifyTests.vb rename to src/Features/VisualBasicTest/FullyQualify/FullyQualifyTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.vb b/src/Features/VisualBasicTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.vb rename to src/Features/VisualBasicTest/GenerateComparisonOperators/GenerateComparisonOperatorsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/GenerateConstructor/GenerateConstructorTests.vb b/src/Features/VisualBasicTest/GenerateConstructor/GenerateConstructorTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/GenerateConstructor/GenerateConstructorTests.vb rename to src/Features/VisualBasicTest/GenerateConstructor/GenerateConstructorTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.vb b/src/Features/VisualBasicTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.vb rename to src/Features/VisualBasicTest/GenerateDefaultConstructors/GenerateDefaultConstructorsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateEndConstruct/GenerateEndConstructTests.vb b/src/Features/VisualBasicTest/GenerateEndConstruct/GenerateEndConstructTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateEndConstruct/GenerateEndConstructTests.vb rename to src/Features/VisualBasicTest/GenerateEndConstruct/GenerateEndConstructTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.vb b/src/Features/VisualBasicTest/GenerateEnumMember/GenerateEnumMemberTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.vb rename to src/Features/VisualBasicTest/GenerateEnumMember/GenerateEnumMemberTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.vb b/src/Features/VisualBasicTest/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.vb rename to src/Features/VisualBasicTest/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateEvent/GenerateEventTests.vb b/src/Features/VisualBasicTest/GenerateEvent/GenerateEventTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateEvent/GenerateEventTests.vb rename to src/Features/VisualBasicTest/GenerateEvent/GenerateEventTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateConversionTests.vb b/src/Features/VisualBasicTest/GenerateMethod/GenerateConversionTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateConversionTests.vb rename to src/Features/VisualBasicTest/GenerateMethod/GenerateConversionTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateMethodTests.vb b/src/Features/VisualBasicTest/GenerateMethod/GenerateMethodTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateMethod/GenerateMethodTests.vb rename to src/Features/VisualBasicTest/GenerateMethod/GenerateMethodTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/GenerateOverrides/GenerateOverridesTests.vb b/src/Features/VisualBasicTest/GenerateOverrides/GenerateOverridesTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/GenerateOverrides/GenerateOverridesTests.vb rename to src/Features/VisualBasicTest/GenerateOverrides/GenerateOverridesTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateType/GenerateTypeTests.vb b/src/Features/VisualBasicTest/GenerateType/GenerateTypeTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateType/GenerateTypeTests.vb rename to src/Features/VisualBasicTest/GenerateType/GenerateTypeTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateType/GenerateTypeTests_Dialog.vb b/src/Features/VisualBasicTest/GenerateType/GenerateTypeTests_Dialog.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateType/GenerateTypeTests_Dialog.vb rename to src/Features/VisualBasicTest/GenerateType/GenerateTypeTests_Dialog.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateVariable/GenerateVariableTests.vb b/src/Features/VisualBasicTest/GenerateVariable/GenerateVariableTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateVariable/GenerateVariableTests.vb rename to src/Features/VisualBasicTest/GenerateVariable/GenerateVariableTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb b/src/Features/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb rename to src/Features/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.vb b/src/Features/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.vb rename to src/Features/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests_FixAllTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb b/src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb rename to src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.vb b/src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.vb rename to src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests_FixAllTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InitializeParameter/AddParameterCheckTests.vb b/src/Features/VisualBasicTest/InitializeParameter/AddParameterCheckTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InitializeParameter/AddParameterCheckTests.vb rename to src/Features/VisualBasicTest/InitializeParameter/AddParameterCheckTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb b/src/Features/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb rename to src/Features/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests.vb b/src/Features/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests.vb rename to src/Features/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests_CrossLanguage.vb b/src/Features/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests_CrossLanguage.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests_CrossLanguage.vb rename to src/Features/VisualBasicTest/InlineMethod/VisualBasicInlineMethodTests_CrossLanguage.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/InlineTemporary/InlineTemporaryTests.vb b/src/Features/VisualBasicTest/InlineTemporary/InlineTemporaryTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/InlineTemporary/InlineTemporaryTests.vb rename to src/Features/VisualBasicTest/InlineTemporary/InlineTemporaryTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/IntroduceParameter/IntroduceParameterTests.vb b/src/Features/VisualBasicTest/IntroduceParameter/IntroduceParameterTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/IntroduceParameter/IntroduceParameterTests.vb rename to src/Features/VisualBasicTest/IntroduceParameter/IntroduceParameterTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/IntroduceUsingStatement/IntroduceUsingStatementTests.vb b/src/Features/VisualBasicTest/IntroduceUsingStatement/IntroduceUsingStatementTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/IntroduceUsingStatement/IntroduceUsingStatementTests.vb rename to src/Features/VisualBasicTest/IntroduceUsingStatement/IntroduceUsingStatementTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/IntroduceVariable/IntroduceLocalForExpressionTests.vb b/src/Features/VisualBasicTest/IntroduceVariable/IntroduceLocalForExpressionTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/IntroduceVariable/IntroduceLocalForExpressionTests.vb rename to src/Features/VisualBasicTest/IntroduceVariable/IntroduceLocalForExpressionTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/IntroduceVariable/IntroduceVariableTests.vb b/src/Features/VisualBasicTest/IntroduceVariable/IntroduceVariableTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/IntroduceVariable/IntroduceVariableTests.vb rename to src/Features/VisualBasicTest/IntroduceVariable/IntroduceVariableTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InvertConditional/InvertConditionalTests.vb b/src/Features/VisualBasicTest/InvertConditional/InvertConditionalTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InvertConditional/InvertConditionalTests.vb rename to src/Features/VisualBasicTest/InvertConditional/InvertConditionalTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InvertIf/InvertMultiLineIfTests.vb b/src/Features/VisualBasicTest/InvertIf/InvertMultiLineIfTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InvertIf/InvertMultiLineIfTests.vb rename to src/Features/VisualBasicTest/InvertIf/InvertMultiLineIfTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InvertIf/InvertSingleLineIfTests.vb b/src/Features/VisualBasicTest/InvertIf/InvertSingleLineIfTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InvertIf/InvertSingleLineIfTests.vb rename to src/Features/VisualBasicTest/InvertIf/InvertSingleLineIfTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/InvertLogical/InvertLogicalTests.vb b/src/Features/VisualBasicTest/InvertLogical/InvertLogicalTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/InvertLogical/InvertLogicalTests.vb rename to src/Features/VisualBasicTest/InvertLogical/InvertLogicalTests.vb diff --git a/src/Features/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests.vbproj b/src/Features/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests.vbproj index 9fee6b6a1ae56..3e24c59e8e94c 100644 --- a/src/Features/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests.vbproj +++ b/src/Features/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests.vbproj @@ -39,20 +39,6 @@ - - - - - - - - - - - - - - @@ -68,9 +54,6 @@ - - - diff --git a/src/EditorFeatures/VisualBasicTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.vb b/src/Features/VisualBasicTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.vb rename to src/Features/VisualBasicTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb b/src/Features/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb rename to src/Features/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/MoveToTopOfFile/MoveToTopOfFileTests.vb b/src/Features/VisualBasicTest/MoveToTopOfFile/MoveToTopOfFileTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/MoveToTopOfFile/MoveToTopOfFileTests.vb rename to src/Features/VisualBasicTest/MoveToTopOfFile/MoveToTopOfFileTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/BasicMoveTypeTestsBase.vb b/src/Features/VisualBasicTest/MoveType/BasicMoveTypeTestsBase.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/BasicMoveTypeTestsBase.vb rename to src/Features/VisualBasicTest/MoveType/BasicMoveTypeTestsBase.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.ActionCountTests.vb b/src/Features/VisualBasicTest/MoveType/MoveTypeTests.ActionCountTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.ActionCountTests.vb rename to src/Features/VisualBasicTest/MoveType/MoveTypeTests.ActionCountTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.vb b/src/Features/VisualBasicTest/MoveType/MoveTypeTests.MoveToNewFile.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.vb rename to src/Features/VisualBasicTest/MoveType/MoveTypeTests.MoveToNewFile.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.RenameFile.vb b/src/Features/VisualBasicTest/MoveType/MoveTypeTests.RenameFile.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.RenameFile.vb rename to src/Features/VisualBasicTest/MoveType/MoveTypeTests.RenameFile.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.RenameType.vb b/src/Features/VisualBasicTest/MoveType/MoveTypeTests.RenameType.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.RenameType.vb rename to src/Features/VisualBasicTest/MoveType/MoveTypeTests.RenameType.vb diff --git a/src/EditorFeatures/VisualBasicTest/NameTupleElement/NameTupleElementTests.vb b/src/Features/VisualBasicTest/NameTupleElement/NameTupleElementTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/NameTupleElement/NameTupleElementTests.vb rename to src/Features/VisualBasicTest/NameTupleElement/NameTupleElementTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/OverloadBase/OverloadBaseTests.vb b/src/Features/VisualBasicTest/OverloadBase/OverloadBaseTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/OverloadBase/OverloadBaseTests.vb rename to src/Features/VisualBasicTest/OverloadBase/OverloadBaseTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests.vb b/src/Features/VisualBasicTest/PreferFrameworkType/PreferFrameworkTypeTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests.vb rename to src/Features/VisualBasicTest/PreferFrameworkType/PreferFrameworkTypeTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.vb b/src/Features/VisualBasicTest/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.vb rename to src/Features/VisualBasicTest/PreferFrameworkType/PreferFrameworkTypeTests_FixAllTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/RemoveSharedFromModuleMembers/RemoveSharedFromModuleMembersTests.vb b/src/Features/VisualBasicTest/RemoveSharedFromModuleMembers/RemoveSharedFromModuleMembersTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/RemoveSharedFromModuleMembers/RemoveSharedFromModuleMembersTests.vb rename to src/Features/VisualBasicTest/RemoveSharedFromModuleMembers/RemoveSharedFromModuleMembersTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/RemoveUnusedVariable/RemoveUnusedVariableTest.vb b/src/Features/VisualBasicTest/RemoveUnusedVariable/RemoveUnusedVariableTest.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/RemoveUnusedVariable/RemoveUnusedVariableTest.vb rename to src/Features/VisualBasicTest/RemoveUnusedVariable/RemoveUnusedVariableTest.vb diff --git a/src/EditorFeatures/VisualBasicTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.vb b/src/Features/VisualBasicTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.vb rename to src/Features/VisualBasicTest/ReplaceConditionalWithStatements/ReplaceConditionalWithStatementsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb b/src/Features/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb rename to src/Features/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.vb b/src/Features/VisualBasicTest/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.vb rename to src/Features/VisualBasicTest/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb b/src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb rename to src/Features/VisualBasicTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/SimplifyThisOrMe/SimplifyThisOrMeTests.vb b/src/Features/VisualBasicTest/SimplifyThisOrMe/SimplifyThisOrMeTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SimplifyThisOrMe/SimplifyThisOrMeTests.vb rename to src/Features/VisualBasicTest/SimplifyThisOrMe/SimplifyThisOrMeTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb b/src/Features/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb rename to src/Features/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb b/src/Features/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb rename to src/Features/VisualBasicTest/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/SpellCheck/SpellCheckSpanTests.vb b/src/Features/VisualBasicTest/SpellCheck/SpellCheckSpanTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SpellCheck/SpellCheckSpanTests.vb rename to src/Features/VisualBasicTest/SpellCheck/SpellCheckSpanTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/Spellcheck/SpellcheckTests.vb b/src/Features/VisualBasicTest/SpellCheck/SpellcheckTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Diagnostics/Spellcheck/SpellcheckTests.vb rename to src/Features/VisualBasicTest/SpellCheck/SpellcheckTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithNext.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_WithPrevious.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithNext.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_Statements_WithPrevious.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithNested.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/MergeNestedIfStatementsTests_WithOuter.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoConsecutiveIfStatementsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.vb b/src/Features/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.vb rename to src/Features/VisualBasicTest/SplitOrMergeIfStatements/SplitIntoNestedIfStatementsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/UseNamedArguments/UseNamedArgumentsTests.vb b/src/Features/VisualBasicTest/UseNamedArguments/UseNamedArgumentsTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/UseNamedArguments/UseNamedArgumentsTests.vb rename to src/Features/VisualBasicTest/UseNamedArguments/UseNamedArgumentsTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Utilities/CodeSnippets.vb b/src/Features/VisualBasicTest/Utilities/CodeSnippets.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Utilities/CodeSnippets.vb rename to src/Features/VisualBasicTest/Utilities/CodeSnippets.vb diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb b/src/Features/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb rename to src/Features/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/ArgumentWrappingTests.vb b/src/Features/VisualBasicTest/Wrapping/ArgumentWrappingTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Wrapping/ArgumentWrappingTests.vb rename to src/Features/VisualBasicTest/Wrapping/ArgumentWrappingTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/BinaryExpressionWrappingTests.vb b/src/Features/VisualBasicTest/Wrapping/BinaryExpressionWrappingTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Wrapping/BinaryExpressionWrappingTests.vb rename to src/Features/VisualBasicTest/Wrapping/BinaryExpressionWrappingTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/ChainedExpressionWrappingTests.vb b/src/Features/VisualBasicTest/Wrapping/ChainedExpressionWrappingTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Wrapping/ChainedExpressionWrappingTests.vb rename to src/Features/VisualBasicTest/Wrapping/ChainedExpressionWrappingTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/InitializerExpressionWrappingTests.vb b/src/Features/VisualBasicTest/Wrapping/InitializerExpressionWrappingTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Wrapping/InitializerExpressionWrappingTests.vb rename to src/Features/VisualBasicTest/Wrapping/InitializerExpressionWrappingTests.vb diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/ParameterWrappingTests.vb b/src/Features/VisualBasicTest/Wrapping/ParameterWrappingTests.vb similarity index 100% rename from src/EditorFeatures/VisualBasicTest/Wrapping/ParameterWrappingTests.vb rename to src/Features/VisualBasicTest/Wrapping/ParameterWrappingTests.vb diff --git a/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets b/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets index b99e993370284..aa85224f576fa 100644 --- a/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets +++ b/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets @@ -47,7 +47,7 @@ - + diff --git a/src/Tools/Source/RunTests/ProcessUtil.cs b/src/Tools/Source/RunTests/ProcessUtil.cs index 2df47acf51016..04e9d02d4992c 100644 --- a/src/Tools/Source/RunTests/ProcessUtil.cs +++ b/src/Tools/Source/RunTests/ProcessUtil.cs @@ -17,6 +17,12 @@ internal static class ProcessUtil { internal static int? TryGetParentProcessId(Process p) { + // System.Management is not supported outside of Windows. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return null; + } + try { ManagementObject mo = new ManagementObject("win32_process.handle='" + p.Id + "'"); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs index 2c6adb096893c..882edf733e694 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs @@ -10,6 +10,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; @@ -67,28 +68,31 @@ public void RequireInitialized() Contract.ThrowIfNull(SemanticModel); } - private static SyntaxNode? GetParentNode(SyntaxNode node) + private static SyntaxNode GetParentNode(SyntaxNode node) => node switch { ExpressionSyntax expression => GetParentNode(expression), PatternSyntax pattern => GetParentNode(pattern), CrefSyntax cref => GetParentNode(cref), - _ => null + _ => node.GetRequiredParent(), }; private static SyntaxNode GetParentNode(ExpressionSyntax expression) { - var lastExpression = expression; - for (SyntaxNode? current = expression; current != null; current = current.Parent) + // Walk all the way up the expression to the non-expression parent. Effectively, once we change an + // expression *within* some larger expression context, we want to stop rewriting any further sibling + // expressions as they could be affected by this change. + + SyntaxNode parent = expression; + for (var current = (SyntaxNode)expression; current != null; current = current.Parent) { - if (current is ExpressionSyntax currentExpression) - { - lastExpression = currentExpression; - } + // if we're in an argument, walk up into that as well as the change in one argument can affect + // other arguments in a call. + if (current is ExpressionSyntax or ArgumentSyntax) + parent = current; } - Contract.ThrowIfNull(lastExpression.Parent); - return lastExpression.Parent; + return parent.GetRequiredParent(); } private static SyntaxNode GetParentNode(PatternSyntax pattern) @@ -117,13 +121,13 @@ private static SyntaxNode GetParentNode(CrefSyntax cref) return topMostCref.Parent; } - protected SyntaxNode SimplifyNode( + protected SyntaxNode? SimplifyNode( TNode node, - SyntaxNode newNode, - SyntaxNode parentNode, + SyntaxNode? newNode, Func simplifier) where TNode : SyntaxNode { + var parentNode = GetParentNode(node); RequireInitialized(); this.CancellationToken.ThrowIfCancellationRequested(); @@ -153,19 +157,6 @@ private static SyntaxNode GetParentNode(CrefSyntax cref) return node; } - protected SyntaxNode SimplifyExpression( - TExpression expression, - SyntaxNode newNode, - Func simplifier) - where TExpression : SyntaxNode - { - var parentNode = GetParentNode(expression); - if (parentNode == null) - return newNode; - - return SimplifyNode(expression, newNode, parentNode, simplifier); - } - protected SyntaxToken SimplifyToken(SyntaxToken token, Func simplifier) { RequireInitialized(); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.Rewriter.cs index 0e1feeb94a0a2..cf92e7867f5ac 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.Rewriter.cs @@ -22,7 +22,7 @@ public Rewriter(ObjectPool pool) public override SyntaxNode VisitCastExpression(CastExpressionSyntax node) { - return SimplifyExpression( + return SimplifyNode( node, newNode: base.VisitCastExpression(node), simplifier: s_simplifyCast); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs index 5eaf06750c7fa..73fc710a70cf9 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs @@ -45,13 +45,10 @@ public Rewriter(ObjectPool pool) } public override SyntaxNode VisitDefaultExpression(DefaultExpressionSyntax node) - { - return SimplifyNode( + => SimplifyNode( node, newNode: base.VisitDefaultExpression(node), - parentNode: node.Parent, simplifier: _simplifyDefaultExpression); - } } } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs index 8246972fde934..7771b9d0a2be0 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs @@ -2,16 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp.Simplification { internal partial class CSharpDefaultExpressionReducer : AbstractCSharpReducer { - private static readonly ObjectPool s_pool = new( - () => new Rewriter(s_pool)); + private static readonly ObjectPool s_pool = new(static () => new Rewriter(s_pool)); public CSharpDefaultExpressionReducer() : base(s_pool) { diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.Rewriter.cs index 97be79eebc13d..6e54bdd4d5e08 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.Rewriter.cs @@ -20,7 +20,7 @@ public Rewriter(ObjectPool pool) public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { - return SimplifyExpression( + return SimplifyNode( node, newNode: base.VisitInvocationExpression(node), simplifier: s_simplifyExtensionMethod); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs index 083b2604f1521..cd2c393828191 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs @@ -7,7 +7,6 @@ using System; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Simplification; @@ -58,7 +57,6 @@ public override SyntaxNode VisitArgument(ArgumentSyntax node) { return SimplifyNode( node, - parentNode: node.Parent, newNode: newNode, simplifier: s_simplifyTupleName); } @@ -67,13 +65,10 @@ public override SyntaxNode VisitArgument(ArgumentSyntax node) } public override SyntaxNode VisitAnonymousObjectMemberDeclarator(AnonymousObjectMemberDeclaratorSyntax node) - { - return SimplifyNode( + => SimplifyNode( node, - parentNode: node.Parent, newNode: base.VisitAnonymousObjectMemberDeclarator(node), simplifier: s_simplifyAnonymousTypeMemberName); - } } } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.Rewriter.cs index 9b71df0d4a4d8..3ff1ea33fb204 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.Rewriter.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; @@ -18,32 +16,23 @@ public Rewriter(ObjectPool pool) { } - public override SyntaxNode VisitParameter(ParameterSyntax node) - { - return SimplifyNode( + public override SyntaxNode? VisitParameter(ParameterSyntax node) + => SimplifyNode( node, newNode: base.VisitParameter(node), - parentNode: node.Parent, simplifier: s_simplifyParameter); - } - public override SyntaxNode VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) - { - return SimplifyNode( + public override SyntaxNode? VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) + => SimplifyNode( node, newNode: base.VisitParenthesizedLambdaExpression(node), - parentNode: node.Parent, simplifier: s_simplifyParenthesizedLambdaExpression); - } - public override SyntaxNode VisitBlock(BlockSyntax node) - { - return SimplifyNode( + public override SyntaxNode? VisitBlock(BlockSyntax node) + => SimplifyNode( node, newNode: base.VisitBlock(node), - parentNode: node.Parent, simplifier: s_simplifyBlock); - } } } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.Rewriter.cs index 97cc32e70b155..9372a6630a503 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.Rewriter.cs @@ -29,7 +29,7 @@ public override SyntaxNode VisitPredefinedType(PredefinedTypeSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitPredefinedType(node), simplifier: s_simplifyName); @@ -47,7 +47,7 @@ public override SyntaxNode VisitAliasQualifiedName(AliasQualifiedNameSyntax node this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitAliasQualifiedName(node), simplifier: s_simplifyName); @@ -65,7 +65,7 @@ public override SyntaxNode VisitQualifiedName(QualifiedNameSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitQualifiedName(node), simplifier: s_simplifyName); @@ -83,7 +83,7 @@ public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyn this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitMemberAccessExpression(node), simplifier: s_simplifyName); @@ -101,7 +101,7 @@ public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitIdentifierName(node), simplifier: s_simplifyName); @@ -119,7 +119,7 @@ public override SyntaxNode VisitGenericName(GenericNameSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitGenericName(node), simplifier: s_simplifyName); @@ -137,7 +137,7 @@ public override SyntaxNode VisitQualifiedCref(QualifiedCrefSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitQualifiedCref(node), simplifier: s_simplifyName); @@ -155,7 +155,7 @@ public override SyntaxNode VisitArrayType(ArrayTypeSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitArrayType(node), simplifier: s_simplifyName); @@ -173,7 +173,7 @@ public override SyntaxNode VisitNullableType(NullableTypeSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitNullableType(node), simplifier: s_simplifyName); @@ -191,7 +191,7 @@ public override SyntaxNode VisitTupleType(TupleTypeSyntax node) this.alwaysSimplify = node.HasAnnotation(Simplifier.Annotation); } - var result = SimplifyExpression( + var result = SimplifyNode( node, newNode: base.VisitTupleType(node), simplifier: s_simplifyName); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.Rewriter.cs index 0589b2adca76f..1b8856325ac8d 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.Rewriter.cs @@ -19,7 +19,7 @@ public Rewriter(ObjectPool pool) : base(pool) public override SyntaxNode VisitNullableType(NullableTypeSyntax node) { - return SimplifyExpression( + return SimplifyNode( node, base.VisitNullableType(node), simplifier: s_simplifyNullableType); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.Rewriter.cs index 9ea73629f4815..d570b35e1a487 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.Rewriter.cs @@ -20,7 +20,7 @@ public Rewriter(ObjectPool pool) public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { - return SimplifyExpression( + return SimplifyNode( node, newNode: base.VisitParenthesizedExpression(node), simplifier: s_simplifyParentheses); diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.Rewriter.cs index bfeb103868fe3..cfb6c0b052cf4 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.Rewriter.cs @@ -20,7 +20,7 @@ public Rewriter(ObjectPool pool) public override SyntaxNode VisitParenthesizedPattern(ParenthesizedPatternSyntax node) { - return SimplifyExpression( + return SimplifyNode( node, newNode: base.VisitParenthesizedPattern(node), simplifier: s_simplifyParentheses); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs index cdedfa9553abf..1b7268ac8f73b 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ConstantTextAndVersionSource.cs @@ -45,6 +45,12 @@ public Task GetValueAsync(LoadTextOptions options, CancellationT public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out TextAndVersion value) => TryGetValue(out value); + public bool TryGetVersion(LoadTextOptions options, out VersionStamp version) + { + version = _value.Version; + return true; + } + public ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) => new(_value.Version); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs index 403fc2f57ce5c..941cb267fc1de 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_TreeTextSource.cs @@ -15,7 +15,7 @@ internal partial class DocumentState /// /// A source for constructed from an syntax tree. /// - private sealed class TreeTextSource : ITextAndVersionSource, ITextVersionable + private sealed class TreeTextSource : ITextAndVersionSource { private readonly ValueSource _textSource; private readonly VersionStamp _version; @@ -55,7 +55,7 @@ public bool TryGetValue(LoadTextOptions options, [NotNullWhen(true)] out TextAnd } } - public bool TryGetTextVersion(LoadTextOptions options, out VersionStamp version) + public bool TryGetVersion(LoadTextOptions options, out VersionStamp version) { version = _version; return version != default; diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs index 0e4b9676e69c5..ab0bc21554dde 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ITextAndVersionSource.cs @@ -20,6 +20,8 @@ internal interface ITextAndVersionSource TextAndVersion GetValue(LoadTextOptions options, CancellationToken cancellationToken); Task GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken); + bool TryGetVersion(LoadTextOptions options, out VersionStamp version); + /// /// Retrieves just the version information from this instance. Cheaper than when only /// the version is needed, and avoiding loading the text is desirable. diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ITextVersionable.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ITextVersionable.cs deleted file mode 100644 index 3d8f25fca28e6..0000000000000 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ITextVersionable.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -namespace Microsoft.CodeAnalysis -{ - internal interface ITextVersionable - { - bool TryGetTextVersion(LoadTextOptions options, out VersionStamp version); - } -} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs b/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs index 9639bc617aa50..94b3467cdf651 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/LoadableTextAndVersionSource.cs @@ -6,8 +6,6 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis; @@ -146,6 +144,18 @@ public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out Text public Task GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken) => GetLazyValue(options).GetValueAsync(cancellationToken); + public bool TryGetVersion(LoadTextOptions options, out VersionStamp version) + { + if (!TryGetValue(options, out var value)) + { + version = default; + return false; + } + + version = value.Version; + return true; + } + public async ValueTask GetVersionAsync(LoadTextOptions options, CancellationToken cancellationToken) { var value = await GetValueAsync(options, cancellationToken).ConfigureAwait(false); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs b/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs index 54b0ed3a5de03..11ad671dd6bd4 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/RecoverableTextAndVersion.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis /// /// A recoverable TextAndVersion source that saves its text to temporary storage. /// - internal sealed class RecoverableTextAndVersion : ITextVersionable, ITextAndVersionSource + internal sealed class RecoverableTextAndVersion : ITextAndVersionSource { private readonly SolutionServices _services; @@ -57,11 +57,9 @@ private bool TryGetInitialSourceOrRecoverableText([NotNullWhen(true)] out ITextA public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out TextAndVersion value) { if (TryGetInitialSourceOrRecoverableText(out var source, out var recoverableText)) - { return source.TryGetValue(options, out value); - } - if (recoverableText.TryGetValue(out var text) && recoverableText.LoadTextOptions == options) + if (recoverableText.LoadTextOptions == options && recoverableText.TryGetValue(out var text)) { value = TextAndVersion.Create(text, recoverableText.Version, recoverableText.LoadDiagnostic); return true; @@ -71,16 +69,14 @@ public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out Text return false; } - public bool TryGetTextVersion(LoadTextOptions options, out VersionStamp version) + public bool TryGetVersion(LoadTextOptions options, out VersionStamp version) { - if (_initialSourceOrRecoverableText is ITextVersionable textVersionable) - { - return textVersionable.TryGetTextVersion(options, out version); - } + if (TryGetInitialSourceOrRecoverableText(out var source, out var recoverableText)) + return source.TryGetVersion(options, out version); - if (TryGetValue(options, out var textAndVersion)) + if (recoverableText.LoadTextOptions == options) { - version = textAndVersion.Version; + version = recoverableText.Version; return true; } @@ -143,7 +139,7 @@ public async ValueTask GetVersionAsync(LoadTextOptions options, Ca return recoverableText.Version; } - private sealed class RecoverableText : WeaklyCachedRecoverableValueSource, ITextVersionable + private sealed class RecoverableText : WeaklyCachedRecoverableValueSource { private readonly ITemporaryStorageServiceInternal _storageService; public readonly VersionStamp Version; diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs index 85b34f69ff7e0..5a8949d62b57c 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs @@ -119,24 +119,7 @@ public bool TryGetText([NotNullWhen(returnValue: true)] out SourceText? text) } public bool TryGetTextVersion(out VersionStamp version) - { - // try fast path first - if (this.TextAndVersionSource is ITextVersionable versionable) - { - return versionable.TryGetTextVersion(LoadTextOptions, out version); - } - - if (this.TextAndVersionSource.TryGetValue(LoadTextOptions, out var textAndVersion)) - { - version = textAndVersion.Version; - return true; - } - else - { - version = default; - return false; - } - } + => TextAndVersionSource.TryGetVersion(LoadTextOptions, out version); public bool TryGetTextAndVersion([NotNullWhen(true)] out TextAndVersion? textAndVersion) => TextAndVersionSource.TryGetValue(LoadTextOptions, out textAndVersion); From 5cf3a315b553d9f55173dd243bd2526c4bf96115 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Mon, 24 Apr 2023 21:33:52 +0000 Subject: [PATCH 191/261] Merged PR 30834: Add component wrapper for telemetry This changes telemetry to use a component wrapper, similar to intellicode. This ensures we don't need MEF to call to the component if it's available, and loads it into it's own ALC. This also removes any dependencies the internal component has on Roslyn code, which allows it to exist in an isolated way. --- Roslyn.sln | 9 +- .../Logging/RoslynLogger.cs | 225 +++++++++++ ...crosoft.CodeAnalysis.LanguageServer.csproj | 1 + .../Program.cs | 21 +- .../Services/AssemblyLoadContextWrapper.cs | 88 ++++ .../Services/Telemetry/TelemetryService.cs | 80 ++++ .../Protocol/ILspFaultLogger.cs | 14 - .../Impl}/.npmrc | 0 ...odeAnalysis.LanguageServer.Internal.csproj | 10 +- ...t.CodeAnalysis.LanguageServer.Internal.sln | 0 .../Impl/VSCodeTelemetryLogger.cs | 176 ++++++++ .../Impl}/package.json | 0 ...s.LanguageServer.Internal.UnitTests.csproj | 34 ++ .../Tests/VSCodeTelemetryLoggerTests.cs | 55 +++ .../VSCodeTelemetryLogger.cs | 379 ------------------ .../Core/Portable/Log/KeyValueLogMessage.cs | 4 +- 16 files changed, 684 insertions(+), 412 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs delete mode 100644 src/Features/LanguageServer/Protocol/ILspFaultLogger.cs rename src/VisualStudio/{Microsoft.CodeAnalysis.LanguageServer.Internal => LanguageServer/Impl}/.npmrc (100%) rename src/VisualStudio/{Microsoft.CodeAnalysis.LanguageServer.Internal => LanguageServer/Impl}/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj (88%) rename src/VisualStudio/{Microsoft.CodeAnalysis.LanguageServer.Internal => LanguageServer/Impl}/Microsoft.CodeAnalysis.LanguageServer.Internal.sln (100%) create mode 100644 src/VisualStudio/LanguageServer/Impl/VSCodeTelemetryLogger.cs rename src/VisualStudio/{Microsoft.CodeAnalysis.LanguageServer.Internal => LanguageServer/Impl}/package.json (100%) create mode 100644 src/VisualStudio/LanguageServer/Tests/Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests.csproj create mode 100644 src/VisualStudio/LanguageServer/Tests/VSCodeTelemetryLoggerTests.cs delete mode 100644 src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs diff --git a/Roslyn.sln b/Roslyn.sln index 9924f75eab083..df247a58c4aee 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -533,7 +533,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Too EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LanguageServer", "LanguageServer", "{D449D505-CC6A-4E0B-AF1B-976E2D0AE67A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.Internal", "src\VisualStudio\Microsoft.CodeAnalysis.LanguageServer.Internal\Microsoft.CodeAnalysis.LanguageServer.Internal.csproj", "{9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.Internal", "src\VisualStudio\LanguageServer\Impl\Microsoft.CodeAnalysis.LanguageServer.Internal.csproj", "{9B7AC5C2-293D-438D-B9A2-1EDDC2C6BF00}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.CSharp.Features.UnitTests", "src\Features\CSharpTest\Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj", "{E645B517-5766-46FB-AA4A-D4D30C9E3BE6}" EndProject @@ -541,6 +541,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Feat EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests", "src\Features\VisualBasicTest\Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests.vbproj", "{57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests", "src\VisualStudio\LanguageServer\Tests\Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests.csproj", "{D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1327,6 +1329,10 @@ Global {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}.Debug|Any CPU.Build.0 = Debug|Any CPU {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}.Release|Any CPU.ActiveCfg = Release|Any CPU {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}.Release|Any CPU.Build.0 = Release|Any CPU + {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1573,6 +1579,7 @@ Global {E645B517-5766-46FB-AA4A-D4D30C9E3BE6} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} {9296F799-5DE4-4E12-A68E-AAC39B0EB90A} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} + {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE} = {8DBA5174-B0AA-4561-82B1-A46607697753} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs new file mode 100644 index 0000000000000..a1f1286e0fa6c --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs @@ -0,0 +1,225 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.Logging +{ + internal class RoslynLogger : ILogger + { + private static RoslynLogger? _instance; + private static readonly ConcurrentDictionary s_eventMap = new(); + private static readonly ConcurrentDictionary<(FunctionId id, string name), string> s_propertyMap = new(); + + private readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); + private static TelemetryService? _telemetryService; + + private RoslynLogger() + { + } + + public static void Initialize(string? telemetryLevel, string? location) + { + Roslyn.Utilities.Contract.ThrowIfTrue(_instance is not null); + + FatalError.Handler = (exception, severity, forceDump) => ReportFault(exception, severity, forceDump); + FatalError.CopyHandlerTo(typeof(Compilation).Assembly); + + if (telemetryLevel is not null && location is not null) + { + _telemetryService = TelemetryService.TryCreate(telemetryLevel, location); + } + + _instance = new(); + + var currentLogger = Logger.GetLogger(); + if (currentLogger is null) + { + Logger.SetLogger(_instance); + } + else + { + Logger.SetLogger(AggregateLogger.Create(currentLogger, _instance)); + } + } + + private static void ReportFault(Exception exception, ErrorSeverity severity, bool forceDump) + { + try + { + if (exception is OperationCanceledException { InnerException: { } oceInnerException }) + { + ReportFault(oceInnerException, severity, forceDump); + return; + } + + if (exception is AggregateException aggregateException) + { + // We (potentially) have multiple exceptions; let's just report each of them + foreach (var innerException in aggregateException.Flatten().InnerExceptions) + ReportFault(innerException, severity, forceDump); + + return; + } + + if (_telemetryService is not null) + { + var eventName = GetEventName(FunctionId.NonFatalWatson); + var description = GetDescription(exception); + var currentProcess = Process.GetCurrentProcess(); + _telemetryService.ReportFault(eventName, description, (int)severity, forceDump, currentProcess.Id, exception); + } + } + catch (OutOfMemoryException) + { + FailFast.OnFatalException(exception); + } + catch (Exception e) + { + FailFast.OnFatalException(e); + } + } + + public bool IsEnabled(FunctionId functionId) + => _telemetryService is not null; + + public void Log(FunctionId functionId, LogMessage logMessage) + { + var name = GetEventName(functionId); + var properties = GetProperties(functionId, logMessage, delta: null); + + try + { + _telemetryService?.Log(name, properties); + } + catch + { + } + } + + public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int blockId, CancellationToken cancellationToken) + { + var eventName = GetEventName(functionId); + var kind = GetKind(logMessage); + + try + { + _telemetryService?.LogBlockStart(eventName, (int)kind, blockId); + } + catch + { + } + } + + public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int blockId, int delta, CancellationToken cancellationToken) + { + var properties = GetProperties(functionId, logMessage, delta); + try + { + _telemetryService?.LogBlockEnd(blockId, properties, cancellationToken); + } + catch + { + } + } + + private static string GetDescription(Exception exception) + { + const string CodeAnalysisNamespace = nameof(Microsoft) + "." + nameof(CodeAnalysis); + + // Be resilient to failing here. If we can't get a suitable name, just fall back to the standard name we + // used to report. + try + { + // walk up the stack looking for the first call from a type that isn't in the ErrorReporting namespace. + var frames = new StackTrace(exception).GetFrames(); + + // On the .NET Framework, GetFrames() can return null even though it's not documented as such. + // At least one case here is if the exception's stack trace itself is null. + if (frames != null) + { + foreach (var frame in frames) + { + var method = frame?.GetMethod(); + var methodName = method?.Name; + if (methodName == null) + continue; + + var declaringTypeName = method?.DeclaringType?.FullName; + if (declaringTypeName == null) + continue; + + if (!declaringTypeName.StartsWith(CodeAnalysisNamespace)) + continue; + + return declaringTypeName + "." + methodName; + } + } + } + catch + { + } + + // If we couldn't get a stack, do this + return exception.Message; + } + + private const string EventPrefix = "vs/ide/vbcs/"; + private const string PropertyPrefix = "vs.ide.vbcs."; + + private static string GetEventName(FunctionId id) + => s_eventMap.GetOrAdd(id, id => EventPrefix + GetTelemetryName(id, separator: '/')); + + private static string GetPropertyName(FunctionId id, string name) + => s_propertyMap.GetOrAdd((id, name), key => PropertyPrefix + GetTelemetryName(id, separator: '.') + "." + key.name.ToLowerInvariant()); + + private static string GetTelemetryName(FunctionId id, char separator) + => Enum.GetName(typeof(FunctionId), id)!.Replace('_', separator).ToLowerInvariant(); + + private static LogType GetKind(LogMessage logMessage) + => logMessage is KeyValueLogMessage kvLogMessage + ? kvLogMessage.Kind + : logMessage.LogLevel switch + { + >= LogLevel.Information => LogType.UserAction, + _ => LogType.Trace + }; + + private static ImmutableDictionary GetProperties(FunctionId id, LogMessage logMessage, int? delta) + { + var builder = ImmutableDictionary.CreateBuilder(); + + if (logMessage is KeyValueLogMessage kvLogMessage) + { + foreach (var (name, val) in kvLogMessage.Properties) + { + builder.Add(GetPropertyName(id, name), val); + } + } + else + { + builder.Add(GetPropertyName(id, "Message"), logMessage.GetMessage()); + } + + if (delta.HasValue) + { + builder.Add(GetPropertyName(id, "Delta"), delta.Value); + } + + return builder.ToImmutableDictionary(); + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 06a8812a7683f..c18d8bee18a1b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -67,6 +67,7 @@ + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 4434094120543..7b1da5f7b0986 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -23,7 +23,7 @@ var parser = CreateCommandLineParser(); return await parser.InvokeAsync(args); -static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, LogLevel minimumLogLevel, string? starredCompletionPath, string? projectRazorJsonFileName, string? telemetryLevel, CancellationToken cancellationToken) +static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, LogLevel minimumLogLevel, string? starredCompletionPath, string? projectRazorJsonFileName, string? telemetryLevel, string? telemetryPath, CancellationToken cancellationToken) { // Before we initialize the LSP server we can't send LSP log messages. // Create a console logger as a fallback to use before the LSP server starts. @@ -75,14 +75,7 @@ static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, } // Initialize the fault handler if it's available - if (telemetryLevel is not null) - { - try - { - exportProvider.GetExportedValue()?.Initialize(telemetryLevel); - } - catch (CompositionFailedException) { } - } + RoslynLogger.Initialize(telemetryLevel, telemetryPath); // Cancellation token source that we can use to cancel on either LSP server shutdown (managed by client) or interrupt. using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -164,11 +157,16 @@ static Parser CreateCommandLineParser() Description = "The file name to use for the project.razor.json file (for Razor projects).", IsRequired = false, }; - var telemetryLevelOption = new Option("--telemetryLevel", getDefaultValue: () => null) + var telemetryLevelOption = new Option("--telemetryLevel") { Description = "Telemetry level, Defaults to 'off'. Example values: 'all', 'crash', 'error', or 'off'.", IsRequired = false, }; + var telemetryPathOption = new Option("--telemetryComponentPath") + { + Description = "The location of the telemetry component (if one exists).", + IsRequired = false + }; var rootCommand = new RootCommand() { @@ -188,8 +186,9 @@ static Parser CreateCommandLineParser() var starredCompletionsPath = context.ParseResult.GetValueForOption(starredCompletionsPathOption); var projectRazorJsonFileName = context.ParseResult.GetValueForOption(projectRazorJsonFileNameOption); var telemetryLevel = context.ParseResult.GetValueForOption(telemetryLevelOption); + var telemetryPath = context.ParseResult.GetValueForOption(telemetryPathOption); - return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, cancellationToken); + return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, telemetryPath, cancellationToken); }); return new CommandLineBuilder(rootCommand).UseDefaults().Build(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs new file mode 100644 index 0000000000000..fca4ace4e7c73 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer.Services +{ + internal class AssemblyLoadContextWrapper : IDisposable + { + private AssemblyLoadContext? _assemblyLoadContext; + private readonly ImmutableDictionary _loadedAssemblies; + private readonly ILogger? _logger; + + private AssemblyLoadContextWrapper(AssemblyLoadContext assemblyLoadContext, ImmutableDictionary loadedFiles, ILogger? logger) + { + _assemblyLoadContext = assemblyLoadContext; + _loadedAssemblies = loadedFiles; + _logger = logger; + } + + public static AssemblyLoadContextWrapper? TryCreate(string name, string assembliesDirectoryPath, ILogger? logger) + { + try + { + var alc = new AssemblyLoadContext(name); + var directory = new DirectoryInfo(assembliesDirectoryPath); + var builder = new Dictionary(); + foreach (var file in directory.GetFiles("*.dll")) + { + builder.Add(file.Name, alc.LoadFromAssemblyPath(file.FullName)); + } + + return new AssemblyLoadContextWrapper(alc, builder.ToImmutableDictionary(), logger); + } + catch (Exception ex) + { + logger?.LogError(ex, "Failed to initialize AssemblyLoadContext {name}", name); + return null; + } + } + + public Assembly GetAssembly(string name) => _loadedAssemblies[name]; + + public MethodInfo? TryGetMethodInfo(string assemblyName, string className, string methodName) + { + try + { + return GetMethodInfo(assemblyName, className, methodName); + } + catch (Exception ex) + { + _logger?.LogError(ex, "Failed to get method information from {assembly} for {class}.{method}", assemblyName, className, methodName); + return null; + } + } + + public MethodInfo GetMethodInfo(string assemblyName, string className, string methodName) + { + var assembly = GetAssembly(assemblyName); + var completionHelperType = assembly.GetType(className); + if (completionHelperType == null) + { + throw new ArgumentException($"{assembly.FullName} assembly did not contain {className} class"); + } + var createCompletionProviderMethodInto = completionHelperType?.GetMethod(methodName); + if (createCompletionProviderMethodInto == null) + { + throw new ArgumentException($"{className} from {assembly.FullName} assembly did not contain {methodName} method"); + } + return createCompletionProviderMethodInto; + } + + public void Dispose() + { + _assemblyLoadContext?.Unload(); + _assemblyLoadContext = null; + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs new file mode 100644 index 0000000000000..2473d9799fb94 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ErrorReporting; + +namespace Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry +{ + internal class TelemetryService : IDisposable + { + private const string AssemblyName = "Microsoft.CodeAnalysis.LanguageServer.Internal.dll"; + private const string ClassName = "Microsoft.CodeAnalysis.LanguageServer.Internal.VSCodeTelemetryLogger"; + + private readonly AssemblyLoadContextWrapper _alcWrapper; + private readonly Lazy _logMethod; + private readonly Lazy _logBlockStartMethod; + private readonly Lazy _logBlockEndMethod; + private readonly Lazy _reportFaultMethod; + + public TelemetryService(AssemblyLoadContextWrapper alcWrapper) + { + _alcWrapper = alcWrapper; + _logMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "Log")); + _logBlockStartMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "LogBlockStart")); + _logBlockEndMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "LogBlockEnd")); + _reportFaultMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "ReportFault")); + } + + public static TelemetryService? TryCreate(string telemetryLevel, string location) + { + var alcService = AssemblyLoadContextWrapper.TryCreate("RoslynVSCodeTelemetry", location, logger: null); + if (alcService is null) + { + return null; + } + + var initializeMethod = alcService.TryGetMethodInfo(AssemblyName, ClassName, "Initialize"); + if (initializeMethod is null) + { + return null; + } + + initializeMethod.Invoke(null, new object[] { telemetryLevel }); + return new(alcService); + } + + public void Dispose() + { + _alcWrapper.Dispose(); + } + + internal void Log(string name, ImmutableDictionary properties) + { + _logMethod.Value.Invoke(null, new object[] { name, properties }); + } + + internal void LogBlockStart(string eventName, int kind, int blockId) + { + _logBlockStartMethod.Value.Invoke(null, new object[] { eventName, kind, blockId }); + } + + internal void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) + { + _logBlockEndMethod.Value.Invoke(null, new object[] { blockId, properties, cancellationToken }); + } + + internal void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) + { + _reportFaultMethod.Value.Invoke(null, new object[] { eventName, description, logLevel, forceDump, processId, exception }); + } + } +} diff --git a/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs b/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs deleted file mode 100644 index b651da7e537dd..0000000000000 --- a/src/Features/LanguageServer/Protocol/ILspFaultLogger.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Microsoft.CodeAnalysis.Internal.Log; - -namespace Microsoft.CodeAnalysis.LanguageServer; - -internal interface ILspFaultLogger -{ - void Initialize(string telemetryLevel); - void ReportFault(Exception exception, LogLevel logLevel, bool forceDump); -} diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/.npmrc b/src/VisualStudio/LanguageServer/Impl/.npmrc similarity index 100% rename from src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/.npmrc rename to src/VisualStudio/LanguageServer/Impl/.npmrc diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj b/src/VisualStudio/LanguageServer/Impl/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj similarity index 88% rename from src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj rename to src/VisualStudio/LanguageServer/Impl/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj index 4a30e5ad9c21e..a002cc09819e2 100644 --- a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj +++ b/src/VisualStudio/LanguageServer/Impl/Microsoft.CodeAnalysis.LanguageServer.Internal.csproj @@ -3,7 +3,7 @@ Library - net6.0 + net7.0 enable true @@ -17,6 +17,10 @@ + + + + $(StageForNpmPackDependsOn);CollectNpmInputs @@ -41,8 +45,4 @@ - - - - diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.sln b/src/VisualStudio/LanguageServer/Impl/Microsoft.CodeAnalysis.LanguageServer.Internal.sln similarity index 100% rename from src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/Microsoft.CodeAnalysis.LanguageServer.Internal.sln rename to src/VisualStudio/LanguageServer/Impl/Microsoft.CodeAnalysis.LanguageServer.Internal.sln diff --git a/src/VisualStudio/LanguageServer/Impl/VSCodeTelemetryLogger.cs b/src/VisualStudio/LanguageServer/Impl/VSCodeTelemetryLogger.cs new file mode 100644 index 0000000000000..b544f9c4ed9f0 --- /dev/null +++ b/src/VisualStudio/LanguageServer/Impl/VSCodeTelemetryLogger.cs @@ -0,0 +1,176 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Text; +using System.Threading; +using Microsoft.VisualStudio.Telemetry; + +namespace Microsoft.CodeAnalysis.LanguageServer.Internal; + +internal static class VSCodeTelemetryLogger +{ + private static TelemetrySession? _telemetrySession; + private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; + private static int _dumpsSubmitted = 0; + + private static readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); + + public static void Initialize(string telemetryLevel) + { + if (_telemetrySession is not null) + { + _telemetrySession.Dispose(); + } + + _telemetrySession = CreateTelemetryService(telemetryLevel); + _telemetrySession.Start(); + } + + public static void Log(string name, ImmutableDictionary properties) + { + var telemetryEvent = new TelemetryEvent(name); + SetProperties(telemetryEvent, properties); + PostEvent(telemetryEvent); + } + + public static void LogBlockStart(string eventName, int kind, int blockId) + { + _pendingScopes[blockId] = kind switch + { + 0 => _telemetrySession.StartOperation(eventName), // LogType.Trace + 1 => _telemetrySession.StartUserTask(eventName), // LogType.UserAction + _ => new InvalidOperationException($"Unknown BlockStart kind: {kind}") + }; + } + + public static void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) + { + var found = _pendingScopes.TryRemove(blockId, out var scope); + Contract.Requires(found); + + var endEvent = GetEndEvent(scope); + SetProperties(endEvent, properties); + + var result = cancellationToken.IsCancellationRequested ? TelemetryResult.UserCancel : TelemetryResult.Success; + + if (scope is TelemetryScope operation) + operation.End(result); + else if (scope is TelemetryScope userTask) + userTask.End(result); + else + throw new InvalidCastException($"Unexpected value for scope: {scope}"); + } + + public static void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) + { + var faultEvent = new FaultEvent( + eventName: eventName, + description: description, + (FaultSeverity)logLevel, + exceptionObject: exception, + gatherEventDetails: faultUtility => + { + if (forceDump) + { + // Let's just send a maximum of three; number chosen arbitrarily + if (Interlocked.Increment(ref _dumpsSubmitted) <= 3) + faultUtility.AddProcessDump(processId); + } + + if (faultUtility is FaultEvent { IsIncludedInWatsonSample: true }) + { + // if needed, add any extra logs here + } + + // Returning "0" signals that, if sampled, we should send data to Watson. + // Any other value will cancel the Watson report. We never want to trigger a process dump manually, + // we'll let TargetedNotifications determine if a dump should be collected. + // See https://aka.ms/roslynnfwdocs for more details + return 0; + }); + + _telemetrySession!.PostEvent(faultEvent); + } + + private static TelemetrySession CreateTelemetryService(string telemetryLevel) + { + var sessionSettingsJson = CreateSessionSettingsJson(telemetryLevel); + TelemetryService.SetDefaultSession(new TelemetrySession($"{{{sessionSettingsJson}}}")); + return TelemetryService.DefaultSession; + } + + private static string CreateSessionSettingsJson(string telemetryLevel) + { + var customSessionId = Guid.NewGuid().ToString(); + + // Generate a new startTime for process to be consumed by Telemetry Settings + using var curProcess = Process.GetCurrentProcess(); + var processStartTime = curProcess.StartTime.ToFileTimeUtc().ToString(); + + var sb = new StringBuilder(); + + var kvp = new Dictionary + { + { "Id", StringToJsonValue(customSessionId) }, + { "HostName", StringToJsonValue("Default") }, + + // Insert Telemetry Level instead of Opt-Out status. The telemetry service handles + // validation of this value so there is no need to do so on this end. If it's invalid, + // it defaults to off. + { "TelemetryLevel", StringToJsonValue(telemetryLevel) }, + + // this sets the Telemetry Session Created by LSP Server to be the Root Initial session + // This means that the SessionID set here by "Id" will be the SessionID used by cloned session + // further down stream + { "IsInitialSession", "true" }, + { "CollectorApiKey", StringToJsonValue(CollectorApiKey) }, + + // using 1010 to indicate VS Code and not to match it to devenv 1000 + { "AppId", "1010" }, + { "ProcessStartTime", processStartTime }, + }; + + foreach (var keyValue in kvp) + { + sb.AppendFormat("\"{0}\":{1},", keyValue.Key, keyValue.Value); + } + + return sb.ToString().TrimEnd(','); + + static string StringToJsonValue(string? value) + { + if (value == null) + { + return "null"; + } + + return '"' + value + '"'; + } + } + + private static TelemetryEvent GetEndEvent(object? scope) + => scope switch + { + TelemetryScope operation => operation.EndEvent, + TelemetryScope userTask => userTask.EndEvent, + _ => throw new InvalidCastException($"Unexpected value for scope: {scope}") + }; + + private static void PostEvent(TelemetryEvent telemetryEvent) + => _telemetrySession?.PostEvent(telemetryEvent); + + private static void SetProperties(TelemetryEvent telemetryEvent, ImmutableDictionary properties) + { + foreach (var (name, value) in properties) + { + telemetryEvent.Properties.Add(name, value); + } + } +} diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/package.json b/src/VisualStudio/LanguageServer/Impl/package.json similarity index 100% rename from src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/package.json rename to src/VisualStudio/LanguageServer/Impl/package.json diff --git a/src/VisualStudio/LanguageServer/Tests/Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests.csproj b/src/VisualStudio/LanguageServer/Tests/Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests.csproj new file mode 100644 index 0000000000000..97628e6f3b773 --- /dev/null +++ b/src/VisualStudio/LanguageServer/Tests/Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests.csproj @@ -0,0 +1,34 @@ + + + + + Library + net7.0 + Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests + UnitTest + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/VisualStudio/LanguageServer/Tests/VSCodeTelemetryLoggerTests.cs b/src/VisualStudio/LanguageServer/Tests/VSCodeTelemetryLoggerTests.cs new file mode 100644 index 0000000000000..c13fc18be9866 --- /dev/null +++ b/src/VisualStudio/LanguageServer/Tests/VSCodeTelemetryLoggerTests.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable disable + +using System; +using System.Collections.Immutable; +using System.IO; +using System.Threading; +using Microsoft.CodeAnalysis.LanguageServer.Services; +using Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry; +using Microsoft.VisualStudio.Telemetry; +using Xunit; +using TelemetryService = Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry.TelemetryService; + +namespace Microsoft.CodeAnalysis.LanguageServer.Internal.UnitTests; + +public class VSCodeTelemetryLoggerTests +{ + private static TelemetryService CreateService() + { + var assembly = typeof(VSCodeTelemetryLogger).Assembly; + var telemetryDirectory = new FileInfo(assembly.Location).Directory.FullName; + var service = TelemetryService.TryCreate("off", telemetryDirectory); + + Assert.NotNull(service); + + return service; + } + + private static string GetEventName(string name) => $"test/event/{name}"; + + [Fact] + public void TestFault() + { + var service = CreateService(); + service.ReportFault(GetEventName(nameof(TestFault)), "test description", (int)FaultSeverity.General, forceDump: false, processId: 0, new Exception()); + } + + [Fact] + public void TestBlockLogging() + { + var service = CreateService(); + service.LogBlockStart(GetEventName(nameof(TestBlockLogging)), kind: 0, blockId: 0); + service.LogBlockEnd(blockId: 0, ImmutableDictionary.Empty, CancellationToken.None); + } + + [Fact] + public void TestLog() + { + var service = CreateService(); + service.Log(GetEventName(nameof(TestLog)), ImmutableDictionary.Empty); + } +} diff --git a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs b/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs deleted file mode 100644 index 0298e6e446c88..0000000000000 --- a/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/VSCodeTelemetryLogger.cs +++ /dev/null @@ -1,379 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Composition; -using System.Diagnostics; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.ErrorReporting; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.Telemetry; -using Microsoft.VisualStudio.Telemetry; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.LanguageServer.Internal; - -[Export(typeof(ILspFaultLogger)), Shared] -internal class VSCodeWorkspaceTelemetryService : ILspFaultLogger, ILogger -{ - private TelemetrySession? _telemetrySession; - private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; - - private static readonly ConcurrentDictionary s_eventMap = new(); - private static readonly ConcurrentDictionary<(FunctionId id, string name), string> s_propertyMap = new(); - - private readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); - - private int _dumpsSubmitted = 0; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSCodeWorkspaceTelemetryService() - { - } - - public void Initialize(string telemetryLevel) - { - _telemetrySession = CreateTelemetryService(telemetryLevel); - _telemetrySession.Start(); - - FatalError.Handler = (exception, severity, forceDump) => ReportFault(exception, ConvertSeverity(severity), forceDump); - FatalError.CopyHandlerTo(typeof(Compilation).Assembly); - - var currentLogger = Logger.GetLogger(); - if (currentLogger is null) - { - Logger.SetLogger(this); - } - else - { - Logger.SetLogger(AggregateLogger.Create(currentLogger, this)); - } - } - - public void ReportFault(Exception exception, LogLevel logLevel, bool forceDump) - { - Assumes.NotNull(_telemetrySession); - - try - { - if (exception is OperationCanceledException { InnerException: { } oceInnerException }) - { - ReportFault(oceInnerException, logLevel, forceDump); - return; - } - - if (exception is AggregateException aggregateException) - { - // We (potentially) have multiple exceptions; let's just report each of them - foreach (var innerException in aggregateException.Flatten().InnerExceptions) - ReportFault(innerException, logLevel, forceDump); - - return; - } - - var currentProcess = Process.GetCurrentProcess(); - var faultEvent = new FaultEvent( - eventName: "vs/ide/vbcs/nonfatalwatson", - description: GetDescription(exception), - ConvertToFaultSeverity(logLevel), - exceptionObject: exception, - gatherEventDetails: faultUtility => - { - if (forceDump) - { - // Let's just send a maximum of three; number chosen arbitrarily - if (Interlocked.Increment(ref _dumpsSubmitted) <= 3) - faultUtility.AddProcessDump(currentProcess.Id); - } - - if (faultUtility is FaultEvent { IsIncludedInWatsonSample: true }) - { - // if needed, add any extra logs here - } - - // Returning "0" signals that, if sampled, we should send data to Watson. - // Any other value will cancel the Watson report. We never want to trigger a process dump manually, - // we'll let TargetedNotifications determine if a dump should be collected. - // See https://aka.ms/roslynnfwdocs for more details - return 0; - }); - - _telemetrySession.PostEvent(faultEvent); - } - catch (OutOfMemoryException) - { - FailFast.OnFatalException(exception); - } - catch (Exception e) - { - FailFast.OnFatalException(e); - } - } - - public bool IsEnabled(FunctionId functionId) - => _telemetrySession?.IsOptedIn ?? false; - - public void Log(FunctionId functionId, LogMessage logMessage) - { - var telemetryEvent = new TelemetryEvent(GetEventName(functionId)); - SetProperties(telemetryEvent, functionId, logMessage, delta: null); - - try - { - PostEvent(telemetryEvent); - } - catch - { - } - } - - public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int blockId, CancellationToken cancellationToken) - { - var eventName = GetEventName(functionId); - var kind = GetKind(logMessage); - - try - { - _pendingScopes[blockId] = Start(eventName, kind); - } - catch - { - } - } - - public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int blockId, int delta, CancellationToken cancellationToken) - { - Contract.ThrowIfFalse(_pendingScopes.TryRemove(blockId, out var scope)); - - var endEvent = GetEndEvent(scope); - SetProperties(endEvent, functionId, logMessage, delta); - - var result = cancellationToken.IsCancellationRequested ? TelemetryResult.UserCancel : TelemetryResult.Success; - - try - { - End(scope, result); - } - catch - { - } - } - - private object Start(string eventName, LogType type) - => type switch - { - LogType.Trace => _telemetrySession.StartOperation(eventName), - LogType.UserAction => _telemetrySession.StartUserTask(eventName), - _ => throw ExceptionUtilities.UnexpectedValue(type), - }; - - private static void End(object scope, TelemetryResult result) - { - if (scope is TelemetryScope operation) - operation.End(result); - else if (scope is TelemetryScope userTask) - userTask.End(result); - else - throw ExceptionUtilities.UnexpectedValue(scope); - } - - private static TelemetryEvent GetEndEvent(object scope) - => scope switch - { - TelemetryScope operation => operation.EndEvent, - TelemetryScope userTask => userTask.EndEvent, - _ => throw ExceptionUtilities.UnexpectedValue(scope) - }; - - private void PostEvent(TelemetryEvent telemetryEvent) - => _telemetrySession?.PostEvent(telemetryEvent); - - private static string GetDescription(Exception exception) - { - const string CodeAnalysisNamespace = nameof(Microsoft) + "." + nameof(CodeAnalysis); - - // Be resilient to failing here. If we can't get a suitable name, just fall back to the standard name we - // used to report. - try - { - // walk up the stack looking for the first call from a type that isn't in the ErrorReporting namespace. - var frames = new StackTrace(exception).GetFrames(); - - // On the .NET Framework, GetFrames() can return null even though it's not documented as such. - // At least one case here is if the exception's stack trace itself is null. - if (frames != null) - { - foreach (var frame in frames) - { - var method = frame?.GetMethod(); - var methodName = method?.Name; - if (methodName == null) - continue; - - var declaringTypeName = method?.DeclaringType?.FullName; - if (declaringTypeName == null) - continue; - - if (!declaringTypeName.StartsWith(CodeAnalysisNamespace)) - continue; - - return declaringTypeName + "." + methodName; - } - } - } - catch - { - } - - // If we couldn't get a stack, do this - return exception.Message; - } - - private static void SetProperties(TelemetryEvent telemetryEvent, FunctionId functionId, LogMessage logMessage, int? delta) - { - if (logMessage is KeyValueLogMessage kvLogMessage) - { - AppendProperties(telemetryEvent, functionId, kvLogMessage); - } - else - { - var message = logMessage.GetMessage(); - if (!string.IsNullOrWhiteSpace(message)) - { - var propertyName = GetPropertyName(functionId, "Message"); - telemetryEvent.Properties.Add(propertyName, message); - } - } - - if (delta.HasValue) - { - var deltaPropertyName = GetPropertyName(functionId, "Delta"); - telemetryEvent.Properties.Add(deltaPropertyName, delta.Value); - } - } - - private static void AppendProperties(TelemetryEvent telemetryEvent, FunctionId functionId, KeyValueLogMessage logMessage) - { - foreach (var (name, value) in logMessage.Properties) - { - // call SetProperty. VS telemetry will take care of finding correct - // API based on given object type for us. - // - // numeric data will show up in ES with measurement prefix. - - telemetryEvent.Properties.Add(GetPropertyName(functionId, name), value switch - { - PiiValue pii => new TelemetryPiiProperty(pii.Value), - IEnumerable items => new TelemetryComplexProperty(items.Select(item => (item is PiiValue pii) ? new TelemetryPiiProperty(pii.Value) : item)), - _ => value - }); - } - } - - private const string EventPrefix = "vs/ide/vbcs/"; - private const string PropertyPrefix = "vs.ide.vbcs."; - - private static string GetEventName(FunctionId id) - => s_eventMap.GetOrAdd(id, id => EventPrefix + GetTelemetryName(id, separator: '/')); - - private static string GetPropertyName(FunctionId id, string name) - => s_propertyMap.GetOrAdd((id, name), key => PropertyPrefix + GetTelemetryName(id, separator: '.') + "." + key.name.ToLowerInvariant()); - - private static string GetTelemetryName(FunctionId id, char separator) - => Enum.GetName(typeof(FunctionId), id)!.Replace('_', separator).ToLowerInvariant(); - - private static LogLevel ConvertSeverity(ErrorSeverity severity) - => severity switch - { - ErrorSeverity.Uncategorized => LogLevel.None, - ErrorSeverity.Diagnostic => LogLevel.Debug, - ErrorSeverity.General => LogLevel.Information, - ErrorSeverity.Critical => LogLevel.Critical, - _ => LogLevel.None - }; - - private static FaultSeverity ConvertToFaultSeverity(LogLevel logLevel) - => logLevel switch - { - > LogLevel.Error => FaultSeverity.Critical, - > LogLevel.Information => FaultSeverity.General, - _ => FaultSeverity.Diagnostic - }; - - private static LogType GetKind(LogMessage logMessage) - => logMessage is KeyValueLogMessage kvLogMessage - ? kvLogMessage.Kind - : logMessage.LogLevel switch - { - >= LogLevel.Information => LogType.UserAction, - _ => LogType.Trace - }; - - private static TelemetrySession CreateTelemetryService(string telemetryLevel) - { - var sessionSettingsJson = CreateSessionSettingsJson(telemetryLevel, customSessionId: null); - TelemetryService.SetDefaultSession(new TelemetrySession($"{{{sessionSettingsJson}}}")); - return TelemetryService.DefaultSession; - } - - private static string CreateSessionSettingsJson(string telemetryLevel, string? customSessionId) - { - // This code exists to use the random string ID generated by VSCode - // If customSessionId was passed in as empty, then generate a new Guid for use. - customSessionId = string.IsNullOrEmpty(customSessionId) ? Guid.NewGuid().ToString() : customSessionId; - - // Generate a new startTime for process to be consumed by Telemetry Settings - using var curProcess = Process.GetCurrentProcess(); - var processStartTime = curProcess.StartTime.ToFileTimeUtc().ToString(); - - var sb = new StringBuilder(); - - var kvp = new Dictionary - { - { "Id", StringToJsonValue(customSessionId) }, - { "HostName", StringToJsonValue("Default") }, - - // Insert Telemetry Level instead of Opt-Out status. The telemetry service handles - // validation of this value so there is no need to do so on this end. If it's invalid, - // it defaults to off. - { "TelemetryLevel", StringToJsonValue(telemetryLevel) }, - - // this sets the Telemetry Session Created by LSP Server to be the Root Initial session - // This means that the SessionID set here by "Id" will be the SessionID used by cloned session - // further down stream - { "IsInitialSession", "true" }, - { "CollectorApiKey", StringToJsonValue(CollectorApiKey) }, - - // using 1010 to indicate VS Code and not to match it to devenv 1000 - { "AppId", "1010" }, - { "ProcessStartTime", processStartTime }, - }; - - foreach (var keyValue in kvp) - { - sb.AppendFormat("\"{0}\":{1},", keyValue.Key, keyValue.Value); - } - - return sb.ToString().TrimEnd(','); - - static string StringToJsonValue(string? value) - { - if (value == null) - { - return "null"; - } - - return '"' + value + '"'; - } - } -} diff --git a/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs b/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs index dbbcc1029dbdc..e6b23bd66a43d 100644 --- a/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs +++ b/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs @@ -176,11 +176,11 @@ internal enum LogType /// /// Log some traces of an activity (default) /// - Trace, + Trace = 0, /// /// Log an user explicit action /// - UserAction, + UserAction = 1, } } From 53a9de1482fd190a4d7d75ed3a89ced55da10de1 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Mon, 24 Apr 2023 16:10:14 -0700 Subject: [PATCH 192/261] Move StarredCompletions to AssemblyContextWrapper --- .../StarredCompletionsAssemblyHelper.cs | 45 ++++--------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs index 9c60ee6a5baf8..40aca97daeba2 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs @@ -6,6 +6,7 @@ using System.Runtime.Loader; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; +using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.Extensions.Logging; using Microsoft.ServiceHub.Framework; using Roslyn.Utilities; @@ -35,9 +36,13 @@ internal static void InitializeInstance(string? completionsAssemblyLocation, ILo var logger = loggerFactory.CreateLogger(typeof(StarredCompletionAssemblyHelper)); try { - var starredCompletionsALC = new AssemblyLoadContext(ALCName); - var starredCompletionsAssembly = LoadSuggestionsAssemblyAndDependencies(starredCompletionsALC, completionsAssemblyLocation); - var createCompletionProviderMethodInfo = GetMethodInfo(starredCompletionsAssembly, CompletionHelperClassFullName, CreateCompletionProviderMethodName); + var alc = AssemblyLoadContextWrapper.TryCreate(ALCName, completionsAssemblyLocation, logger); + if (alc is null) + { + return; + } + + var createCompletionProviderMethodInfo = alc.GetMethodInfo(CompletionsDllName, CompletionHelperClassFullName, CreateCompletionProviderMethodName); _completionProviderLazy = new AsyncLazy(c => CreateCompletionProviderAsync( createCompletionProviderMethodInfo, serviceBroker, @@ -61,40 +66,6 @@ internal static void InitializeInstance(string? completionsAssemblyLocation, ILo return null; } - private static Assembly LoadSuggestionsAssemblyAndDependencies(AssemblyLoadContext alc, string assemblyLocation) - { - Assembly? starredSuggestionsAssembly = null; - var directory = new DirectoryInfo(assemblyLocation); - foreach (var file in directory.EnumerateFiles("*.dll")) - { - var assembly = alc.LoadFromAssemblyPath(file.FullName); - if (file.Name == CompletionsDllName) - { - starredSuggestionsAssembly = assembly; - } - } - if (starredSuggestionsAssembly == null) - { - throw new FileNotFoundException($"Required assembly {CompletionsDllName} could not be found"); - } - return starredSuggestionsAssembly; - } - - private static MethodInfo GetMethodInfo(Assembly assembly, string className, string methodName) - { - var completionHelperType = assembly.GetType(className); - if (completionHelperType == null) - { - throw new ArgumentException($"{assembly.FullName} assembly did not contain {className} class"); - } - var createCompletionProviderMethodInto = completionHelperType?.GetMethod(methodName); - if (createCompletionProviderMethodInto == null) - { - throw new ArgumentException($"{className} from {assembly.FullName} assembly did not contain {methodName} method"); - } - return createCompletionProviderMethodInto; - } - private static async Task CreateCompletionProviderAsync(MethodInfo createCompletionProviderMethodInfo, IServiceBroker serviceBroker, string modelBasePath, ILogger logger) { var completionProviderObj = createCompletionProviderMethodInfo.Invoke(null, new object[4] { serviceBroker, Descriptors.RemoteModelService, modelBasePath, logger }); From 7a4b41d4f4d2b4e9010723ac3e326e8ee0340c83 Mon Sep 17 00:00:00 2001 From: tmat Date: Mon, 24 Apr 2023 17:33:35 -0700 Subject: [PATCH 193/261] Fix --- .../Diagnostics/PullDiagnosticTests.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs index 0c8a759303fe7..ca4c927e94b51 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.EditAndContinue; using Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -298,7 +297,7 @@ public async Task TestNoChangeIfDocumentDiagnosticsCalledTwice(bool useVSDiagnos [Theory, CombinatorialData] [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1481208")] - public async Task TestDocumentDiagnosticsWhenEnCVersionChanges(bool useVSDiagnostics, bool mutatingLspWorkspace) + public async Task TestDocumentDiagnosticsWhenGlobalStateChanges(bool useVSDiagnostics, bool mutatingLspWorkspace) { var markup = @"class A {"; @@ -317,10 +316,9 @@ public async Task TestDocumentDiagnosticsWhenEnCVersionChanges(bool useVSDiagnos var resultId = results.Single().ResultId; - // Create a fake diagnostic to trigger a change in edit and continue, without a document change - var encDiagnosticsSource = testLspServer.TestWorkspace.ExportProvider.GetExportedValue(); - var rudeEdits = ImmutableArray.Create((document.Id, ImmutableArray.Create(new RudeEditDiagnostic(RudeEditKind.Update, default)))); - encDiagnosticsSource.ReportDiagnostics(testLspServer.TestWorkspace, testLspServer.TestWorkspace.CurrentSolution, ImmutableArray.Empty, rudeEdits); + // Trigger refresh due to a change to global state that affects diagnostics. + var refresher = testLspServer.TestWorkspace.ExportProvider.GetExportedValue(); + refresher.RequestWorkspaceRefresh(); results = await RunGetDocumentPullDiagnosticsAsync( testLspServer, document.GetURI(), useVSDiagnostics, previousResultId: resultId); From 7dff3dbaf7ead83aba6554dd126d6d587197ae78 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Tue, 25 Apr 2023 21:54:23 +0000 Subject: [PATCH 194/261] Merged PR 30844: Reduce payload size for completion request first part of https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1804538 The benchmark result (for 10k items) Before: ``` BenchmarkDotNet=v0.13.0, OS=Windows 10.0.22621 Intel Core i9-10885H CPU 2.40GHz, 1 CPU, 16 logical and 8 physical cores [Host] : .NET Framework 4.8 (4.8.9139.0), X86 LegacyJIT Job-FTOBUC : .NET Framework 4.8 (4.8.9139.0), X86 LegacyJIT InvocationCount=1 UnrollFactor=1 | Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | |-------------- |---------:|--------:|--------:|----------:|----------:|------:|----------:| | Serialization | 148.4 ms | 1.94 ms | 1.81 ms | 2000.0000 | 2000.0000 | - | 24 MB | ``` after ``` BenchmarkDotNet=v0.13.0, OS=Windows 10.0.22621 Intel Core i9-10885H CPU 2.40GHz, 1 CPU, 16 logical and 8 physical cores [Host] : .NET Framework 4.8 (4.8.9139.0), X86 LegacyJIT Job-FTOBUC : .NET Framework 4.8 (4.8.9139.0), X86 LegacyJIT InvocationCount=1 UnrollFactor=1 | Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | |-------------- |---------:|---------:|---------:|----------:|----------:|------:|----------:| | Serialization | 56.02 ms | 1.699 ms | 4.873 ms | 1000.0000 | 1000.0000 | - | 10 MB | ``` --- eng/Versions.props | 2 +- ...ditorLspCompletionResultCreationService.cs | 32 ++-- .../AbstractLanguageServerProtocolTests.cs | 1 + .../Completion/CompletionCapabilityHelper.cs | 62 ++++++ .../Handler/Completion/CompletionHandler.cs | 93 ++++----- .../CompletionHandler_CreateLspList.cs | 75 ++++---- .../Completion/CompletionResolveData.cs | 5 +- .../Completion/CompletionResolveHandler.cs | 10 +- ...faultLspCompletionResultCreationService.cs | 27 ++- .../ILspCompletionResultCreationService.cs | 2 +- .../Completion/LspCompletionUtilities.cs | 20 +- .../Protocol/LspOptionsStorage.cs | 1 + .../Completion/CompletionTests.cs | 58 +++--- .../LspCompletionSerializationBenchmarks.cs | 178 ++++++++++++++++++ 14 files changed, 399 insertions(+), 167 deletions(-) create mode 100644 src/Features/LanguageServer/Protocol/Handler/Completion/CompletionCapabilityHelper.cs create mode 100644 src/Tools/IdeBenchmarks/Lsp/LspCompletionSerializationBenchmarks.cs diff --git a/eng/Versions.props b/eng/Versions.props index 83e4f2a978c8b..87fa3a544a96a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -32,7 +32,7 @@ 6.0.0-rtm.21518.12 6.0.0-rtm.21518.12 17.7.4-preview - 17.7.6-preview + 17.7.7-preview 17.6.35829 16.10.0 + + + + + + diff --git a/src/Analyzers/Core/Analyzers/AnalyzersResources.resx b/src/Analyzers/Core/Analyzers/AnalyzersResources.resx index 7c0e9510cc6f7..df9dabaf42ade 100644 --- a/src/Analyzers/Core/Analyzers/AnalyzersResources.resx +++ b/src/Analyzers/Core/Analyzers/AnalyzersResources.resx @@ -352,6 +352,27 @@ Simplify LINQ expression + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Fix formatting @@ -376,4 +397,4 @@ Simplify check - \ No newline at end of file + diff --git a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs index 9fba7cf7c47c1..6877fbc7a39d5 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs @@ -19,12 +19,30 @@ internal abstract class AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer GetDescriptors(LocalizableSt { classificationIdDescriptor = CreateDescriptorWithId(IDEDiagnosticIds.RemoveUnnecessaryImportsDiagnosticId, EnforceOnBuildValues.RemoveUnnecessaryImports, titleAndMessage, isUnnecessary: true); generatedCodeClassificationIdDescriptor = CreateDescriptorWithId(IDEDiagnosticIds.RemoveUnnecessaryImportsDiagnosticId + "_gen", EnforceOnBuild.Never, titleAndMessage, isUnnecessary: true, isConfigurable: false); - return ImmutableArray.Create(s_fixableIdDescriptor, classificationIdDescriptor, generatedCodeClassificationIdDescriptor); + return ImmutableArray.Create(s_fixableIdDescriptor, s_enableGenerateDocumentationFileIdDescriptor, classificationIdDescriptor, generatedCodeClassificationIdDescriptor); } protected abstract ISyntaxFacts SyntaxFacts { get; } @@ -54,13 +72,13 @@ private static ImmutableArray GetDescriptors(LocalizableSt protected override void InitializeWorker(AnalysisContext context) { context.RegisterSemanticModelAction(AnalyzeSemanticModel); + context.RegisterCompilationAction(AnalyzeCompilation); } private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) { var tree = context.SemanticModel.SyntaxTree; var cancellationToken = context.CancellationToken; - var language = context.SemanticModel.Language; var unnecessaryImports = UnnecessaryImportsProvider.GetUnnecessaryImports(context.SemanticModel, cancellationToken); if (unnecessaryImports.Any()) @@ -87,6 +105,26 @@ private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) } } + private void AnalyzeCompilation(CompilationAnalysisContext context) + { + // Due to https://github.com/dotnet/roslyn/issues/41640, enabling this analyzer (IDE0005) on build requires users + // to enable generation of XML documentation comments. We detect if generation of XML documentation comments + // is disabled for this tree and IDE0005 diagnostics are being reported with effective severity "Warning" or "Error". + // If so, we report a special diagnostic that recommends the users to set "GenerateDocumentationFile" to "true" + // in their project file to enable IDE0005 on build. + + var compilation = context.Compilation; + var tree = compilation.SyntaxTrees.FirstOrDefault(tree => !GeneratedCodeUtilities.IsGeneratedCode(tree, IsRegularCommentOrDocComment, context.CancellationToken)); + if (tree is null || tree.Options.DocumentationMode != DocumentationMode.None) + return; + + var effectiveSeverity = _classificationIdDescriptor.GetEffectiveSeverity(compilation.Options, tree, context.Options); + if (effectiveSeverity is ReportDiagnostic.Warn or ReportDiagnostic.Error) + { + context.ReportDiagnostic(Diagnostic.Create(s_enableGenerateDocumentationFileIdDescriptor, Location.None)); + } + } + private IEnumerable GetContiguousSpans(ImmutableArray nodes) { var syntaxFacts = this.SyntaxFacts; diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf index 12be2edb8ab0e..115a2de2cbcc1 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf @@ -37,6 +37,35 @@ Přidat modifikátor jen pro čtení + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Přidat kvalifikaci this nebo Me @@ -312,6 +341,16 @@ Odebrat nepoužité soukromé členy + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Zjednodušit výraz LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf index c0c81acd80f5d..efa62afd84999 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf @@ -37,6 +37,35 @@ Modifizierer "readonly" hinzufügen + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Qualifizierung 'this' oder 'Me' hinzufügen @@ -312,6 +341,16 @@ Nicht verwendete private Member entfernen + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression LINQ-Ausdruck vereinfachen diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf index 1dab8b8ce0b05..51bbf57b6c93f 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf @@ -37,6 +37,35 @@ Agregar modificador de solo lectura + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Agregar calificación 'this' o 'Me' @@ -312,6 +341,16 @@ Quitar miembros privados no utilizados + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Simplificar la expresión LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf index 1f7ce6e176138..e11c2ad4c8d9f 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf @@ -37,6 +37,35 @@ Ajouter un modificateur readonly + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Ajoutez la qualification « this » ou « Me ». @@ -312,6 +341,16 @@ Supprimer les membres privés non utilisés + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Simplifier l'expression LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf index 9306efc27203f..d7dc1d890cd13 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf @@ -37,6 +37,35 @@ Aggiungi modificatore readonly + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Aggiunge la qualificazione 'this' o 'Me' @@ -312,6 +341,16 @@ Rimuovi i membri privati inutilizzati + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Semplifica l'espressione LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf index 36577b2a7d4bd..1b5686d68195f 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf @@ -37,6 +37,35 @@ 読み取り専用修飾子を追加します + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification this' または 'Me' 修飾子を追加する @@ -312,6 +341,16 @@ 使用されていないプライベート メンバーを削除する + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression LINQ 式を簡略化する diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf index 3640249d7da74..01d6e219e55b0 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf @@ -37,6 +37,35 @@ 읽기 전용 한정자 추가 + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification 'this' 또는 'Me' 한정자를 추가합니다. @@ -312,6 +341,16 @@ 사용되지 않는 private 멤버 제거 + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression LINQ 식 단순화 diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf index a52bd4f1e65f0..898cd3d967f4d 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf @@ -37,6 +37,35 @@ Dodaj modyfikator tylko do odczytu + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Dodaj kwalifikacje „this” lub „Me” @@ -312,6 +341,16 @@ Usuń nieużywane prywatne składowe + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Uprość wyrażenie LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf index 483beb3e85420..be6f44229d358 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf @@ -37,6 +37,35 @@ Adicionar modificador somente leitura + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Adicionar a qualificação 'este' ou 'Eu' @@ -312,6 +341,16 @@ Remover membros privados não utilizados + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Simplificar a expressão LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf index 90548d064d0a1..39e2c548d565a 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf @@ -37,6 +37,35 @@ Добавить модификатор только для чтения + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification Добавьте квалификацию \"this\" или \"Me\" @@ -312,6 +341,16 @@ Удалите неиспользуемые закрытые члены + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression Упростите выражение LINQ diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf index 9dd7aaa35b7ad..adbd53f35275d 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf @@ -37,6 +37,35 @@ Salt okunur değiştirici ekle + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification 'this' veya 'Me' niteliği ekle @@ -312,6 +341,16 @@ Kullanılmayan özel üyeleri kaldır + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression LINQ ifadesini basitleştir diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf index 7ded05062a88b..905c03f297c1d 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf @@ -37,6 +37,35 @@ 添加只读修饰符 + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification 添加 “this” 或 “Me” 限定 @@ -312,6 +341,16 @@ 删除未使用的私有成员 + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression 简化 LINQ 表达式 diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf index 3ee53e76fea0a..7859c31daefe8 100644 --- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf +++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf @@ -37,6 +37,35 @@ 新增唯讀修飾元 + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + Add the following PropertyGroup to your MSBuild project file to enable IDE0005 (Remove unnecessary usings/imports) on build: + <PropertyGroup> + <!-- + Make sure any documentation comments which are included in code get checked for syntax during the build, but do + not report warnings for missing comments. + CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do) + CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' + CS1712: Type parameter 'type_parameter' has no matching typeparam tag in the XML comment on 'type_or_member' (but other type parameters do) + --> + <GenerateDocumentationFile>True</GenerateDocumentationFile> + <NoWarn>$(NoWarn),1573,1591,1712</NoWarn> + </PropertyGroup> + + + Add 'this' or 'Me' qualification 新增 'this' 或 'Me' 限定性條件。 @@ -312,6 +341,16 @@ 刪除未使用的私用成員 + + Set MSBuild property 'GenerateDocumentationFile' to 'true' + Set MSBuild property 'GenerateDocumentationFile' to 'true' + + + + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + Set MSBuild property 'GenerateDocumentationFile' to 'true' in project file to enable IDE0005 (Remove unnecessary usings/imports) on build + + Simplify LINQ expression 簡化 LINQ 運算式 diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 7440e4a2216f0..4c6b1fab7c27c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -547,6 +547,7 @@ public static CheckConstraintsArgsBoxed Allocate(CSharpCompilation currentCompil public void Free() { + this.Args = default; s_checkConstraintsArgsBoxedPool.Free(this); } } diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs index 1a727046665cc..ab42b9a5bf259 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs @@ -510,5 +510,35 @@ static async Task M(bool b, int i) "; VerifyFlowGraphAndDiagnosticsForTest(source, expectedFlowGraph, expectedDiagnostics); } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67616")] + public void TestAwaitExpression_InStatement() + { + string source = @" +using System.Threading.Tasks; + +class C +{ + static async Task M() + { + /**/await M2()/**/; + } + + static Task M2() => throw null; +} +"; + string expectedOperationTree = @" +IAwaitOperation (OperationKind.Await, Type: System.String) (Syntax: 'await M2()') + Expression: + IInvocationOperation (System.Threading.Tasks.Task C.M2()) (OperationKind.Invocation, Type: System.Threading.Tasks.Task) (Syntax: 'M2()') + Instance Receiver: + null + Arguments(0) +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } } } diff --git a/src/Compilers/Core/CodeAnalysisTest/Collections/SegmentedArrayHelperTests.cs b/src/Compilers/Core/CodeAnalysisTest/Collections/SegmentedArrayHelperTests.cs index a014c55e8adc0..6580ae148a424 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Collections/SegmentedArrayHelperTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Collections/SegmentedArrayHelperTests.cs @@ -4,6 +4,11 @@ #nullable disable +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Microsoft.CodeAnalysis.Collections.Internal; using Roslyn.Utilities; using Xunit; @@ -12,6 +17,88 @@ namespace Microsoft.CodeAnalysis.UnitTests.Collections { public class SegmentedArrayHelperTests { + [StructLayout(LayoutKind.Sequential, Size = 2)] + private struct Size2 { } + + [StructLayout(LayoutKind.Sequential, Size = 4)] + private struct Size4 { } + + [StructLayout(LayoutKind.Sequential, Size = 8)] + private struct Size8 { } + + [StructLayout(LayoutKind.Sequential, Size = 12)] + private struct Size12 { } + + [StructLayout(LayoutKind.Sequential, Size = 16)] + private struct Size16 { } + + [StructLayout(LayoutKind.Sequential, Size = 24)] + private struct Size24 { } + + [StructLayout(LayoutKind.Sequential, Size = 28)] + private struct Size28 { } + + [StructLayout(LayoutKind.Sequential, Size = 32)] + private struct Size32 { } + + [StructLayout(LayoutKind.Sequential, Size = 40)] + private struct Size40 { } + + public static IEnumerable ExplicitSizeTypes + { + get + { + yield return new object[] { typeof(Size2) }; + yield return new object[] { typeof(Size4) }; + yield return new object[] { typeof(Size8) }; + yield return new object[] { typeof(Size12) }; + yield return new object[] { typeof(Size16) }; + yield return new object[] { typeof(Size24) }; + yield return new object[] { typeof(Size28) }; + yield return new object[] { typeof(Size32) }; + yield return new object[] { typeof(Size40) }; + } + } + + [Theory] + [MemberData(nameof(ExplicitSizeTypes))] + public void ExplicitSizesAreCorrect(Type type) + { + Assert.Equal(int.Parse(type.Name[4..]), InvokeUnsafeSizeOf(type)); + } + + [Theory] + [MemberData(nameof(ExplicitSizeTypes))] + public void GetSegmentSize(Type type) + { + var getSegmentSizeMethod = typeof(SegmentedArrayHelper).GetMethod(nameof(SegmentedArrayHelper.GetSegmentSize), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type); + Assert.Equal(SegmentedArrayHelper.TestAccessor.CalculateSegmentSize(InvokeUnsafeSizeOf(type)), (int)getSegmentSizeMethod.Invoke(null, null)); + } + + [Theory] + [MemberData(nameof(ExplicitSizeTypes))] + public void GetSegmentShift(Type type) + { + var getSegmentShiftMethod = typeof(SegmentedArrayHelper).GetMethod(nameof(SegmentedArrayHelper.GetSegmentShift), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type); + var segmentSize = SegmentedArrayHelper.TestAccessor.CalculateSegmentSize(InvokeUnsafeSizeOf(type)); + Assert.Equal(SegmentedArrayHelper.TestAccessor.CalculateSegmentShift(segmentSize), (int)getSegmentShiftMethod.Invoke(null, null)); + } + + [Theory] + [MemberData(nameof(ExplicitSizeTypes))] + public void GetOffsetMask(Type type) + { + var getOffsetMaskMethod = typeof(SegmentedArrayHelper).GetMethod(nameof(SegmentedArrayHelper.GetOffsetMask), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type); + var segmentSize = SegmentedArrayHelper.TestAccessor.CalculateSegmentSize(InvokeUnsafeSizeOf(type)); + Assert.Equal(SegmentedArrayHelper.TestAccessor.CalculateOffsetMask(segmentSize), (int)getOffsetMaskMethod.Invoke(null, null)); + } + + private static int InvokeUnsafeSizeOf(Type type) + { + var unsafeSizeOfMethod = typeof(Unsafe).GetMethod(nameof(Unsafe.SizeOf)).MakeGenericMethod(type); + return (int)unsafeSizeOfMethod.Invoke(null, null); + } + [Theory] [InlineData(1)] [InlineData(2)] diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.DeclarationAnalysisData.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.DeclarationAnalysisData.cs index c2efcb915d223..919cb2d3869a9 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.DeclarationAnalysisData.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.DeclarationAnalysisData.cs @@ -2,53 +2,56 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Immutable; +using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.Diagnostics { internal abstract partial class AnalyzerDriver { - internal sealed class DeclarationAnalysisData + internal readonly struct DeclarationAnalysisData { - public DeclarationAnalysisData( - SyntaxNode declaringReferenceSyntax, - SyntaxNode topmostNodeForAnalysis, - ImmutableArray declarationsInNodeBuilder, - ImmutableArray descendantNodesToAnalyze, - bool isPartialAnalysis) - { - DeclaringReferenceSyntax = declaringReferenceSyntax; - TopmostNodeForAnalysis = topmostNodeForAnalysis; - DeclarationsInNode = declarationsInNodeBuilder; - DescendantNodesToAnalyze = descendantNodesToAnalyze; - IsPartialAnalysis = isPartialAnalysis; - } - /// /// GetSyntax() for the given SyntaxReference. /// - public SyntaxNode DeclaringReferenceSyntax { get; } + public readonly SyntaxNode DeclaringReferenceSyntax; /// /// Topmost declaration node for analysis. /// - public SyntaxNode TopmostNodeForAnalysis { get; } + public readonly SyntaxNode TopmostNodeForAnalysis; /// /// All member declarations within the declaration. /// - public ImmutableArray DeclarationsInNode { get; } + public readonly ImmutableArray DeclarationsInNode; /// /// All descendant nodes for syntax node actions. /// - public ImmutableArray DescendantNodesToAnalyze { get; } + public readonly ArrayBuilder DescendantNodesToAnalyze = ArrayBuilder.GetInstance(); /// /// Flag indicating if this is a partial analysis. /// - public bool IsPartialAnalysis { get; } + public readonly bool IsPartialAnalysis; + + public DeclarationAnalysisData( + SyntaxNode declaringReferenceSyntax, + SyntaxNode topmostNodeForAnalysis, + ImmutableArray declarationsInNodeBuilder, + bool isPartialAnalysis) + { + DeclaringReferenceSyntax = declaringReferenceSyntax; + TopmostNodeForAnalysis = topmostNodeForAnalysis; + DeclarationsInNode = declarationsInNodeBuilder; + IsPartialAnalysis = isPartialAnalysis; + } + + public void Free() + { + DescendantNodesToAnalyze.Free(); + } } } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index a40cdd944c7b8..96aa7f1ec486e 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -646,11 +646,8 @@ internal async Task AttachQueueAndProcessAllEventsAsync(AsyncQueue declarationInfos = builder.ToImmutableAndFree(); bool isPartialDeclAnalysis = analysisScope.FilterSpanOpt.HasValue && !analysisScope.ContainsSpan(topmostNodeForAnalysis.FullSpan); - ImmutableArray nodesToAnalyze = GetSyntaxNodesToAnalyze(topmostNodeForAnalysis, symbol, declarationInfos, semanticModel, cancellationToken); - return new DeclarationAnalysisData(declaringReferenceSyntax, topmostNodeForAnalysis, declarationInfos, nodesToAnalyze, isPartialDeclAnalysis); + var data = new DeclarationAnalysisData(declaringReferenceSyntax, topmostNodeForAnalysis, declarationInfos, isPartialDeclAnalysis); + AddSyntaxNodesToAnalyze(topmostNodeForAnalysis, symbol, declarationInfos, semanticModel, data.DescendantNodesToAnalyze, cancellationToken); + return data; } private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymbol declaredSymbol, SyntaxNode declaringReferenceSyntax, SyntaxNode topmostNodeForAnalysis, ArrayBuilder builder, CancellationToken cancellationToken) @@ -2496,16 +2494,16 @@ private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymb GetOrCreateSemanticModel(decl.SyntaxTree, symbolEvent.Compilation); var declarationAnalysisData = ComputeDeclarationAnalysisData(symbol, decl, semanticModel, analysisScope, cancellationToken); - if (!analysisScope.ShouldAnalyze(declarationAnalysisData.TopmostNodeForAnalysis)) + if (analysisScope.ShouldAnalyze(declarationAnalysisData.TopmostNodeForAnalysis)) { - return; - } + // Execute stateless syntax node actions. + executeNodeActions(); - // Execute stateless syntax node actions. - executeNodeActions(); + // Execute actions in executable code: code block actions, operation actions and operation block actions. + executeExecutableCodeActions(); + } - // Execute actions in executable code: code block actions, operation actions and operation block actions. - executeExecutableCodeActions(); + declarationAnalysisData.Free(); return; @@ -2514,12 +2512,12 @@ void executeNodeActions() if (shouldExecuteSyntaxNodeActions) { var nodesToAnalyze = declarationAnalysisData.DescendantNodesToAnalyze; - executeNodeActionsByKind(analysisScope, nodesToAnalyze, coreActions, arePerSymbolActions: false); - executeNodeActionsByKind(analysisScope, nodesToAnalyze, additionalPerSymbolActions, arePerSymbolActions: true); + executeNodeActionsByKind(nodesToAnalyze, coreActions, arePerSymbolActions: false); + executeNodeActionsByKind(nodesToAnalyze, additionalPerSymbolActions, arePerSymbolActions: true); } } - void executeNodeActionsByKind(AnalysisScope analysisScope, ImmutableArray nodesToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions) + void executeNodeActionsByKind(ArrayBuilder nodesToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions) { foreach (var (analyzer, groupedActionsForAnalyzer) in groupedActions.GroupedActionsByAnalyzer) { @@ -2534,11 +2532,31 @@ void executeNodeActionsByKind(AnalysisScope analysisScope, ImmutableArray.GetInstance(nodesToAnalyze.Count); + foreach (var node in nodesToAnalyze) + { + if (analysisScope.ShouldAnalyze(node)) + filteredNodesToAnalyze.Add(node); + } - AnalyzerExecutor.ExecuteSyntaxNodeActions(filteredNodesToAnalyze, nodeActionsByKind, + executeSyntaxNodeActions(analyzer, groupedActionsForAnalyzer, filteredNodesToAnalyze); + filteredNodesToAnalyze.Free(); + } + else + { + executeSyntaxNodeActions(analyzer, groupedActionsForAnalyzer, nodesToAnalyze); + } + } + + void executeSyntaxNodeActions( + DiagnosticAnalyzer analyzer, + GroupedAnalyzerActionsForAnalyzer groupedActionsForAnalyzer, + ArrayBuilder filteredNodesToAnalyze) + { + AnalyzerExecutor.ExecuteSyntaxNodeActions( + filteredNodesToAnalyze, groupedActionsForAnalyzer.NodeActionsByAnalyzerAndKind, analyzer, semanticModel, _getKind, declarationAnalysisData.TopmostNodeForAnalysis.FullSpan, symbol, isInGeneratedCode, hasCodeBlockStartOrSymbolStartActions: groupedActionsForAnalyzer.HasCodeBlockStartActions || arePerSymbolActions, cancellationToken); @@ -2623,12 +2641,12 @@ void executeOperationsActions(ImmutableArray operationsToAnalyze) { if (shouldExecuteOperationActions) { - executeOperationsActionsByKind(analysisScope, operationsToAnalyze, coreActions, arePerSymbolActions: false); - executeOperationsActionsByKind(analysisScope, operationsToAnalyze, additionalPerSymbolActions, arePerSymbolActions: true); + executeOperationsActionsByKind(operationsToAnalyze, coreActions, arePerSymbolActions: false); + executeOperationsActionsByKind(operationsToAnalyze, additionalPerSymbolActions, arePerSymbolActions: true); } } - void executeOperationsActionsByKind(AnalysisScope analysisScope, ImmutableArray operationsToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions) + void executeOperationsActionsByKind(ImmutableArray operationsToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions) { foreach (var (analyzer, groupedActionsForAnalyzer) in groupedActions.GroupedActionsByAnalyzer) { @@ -2726,11 +2744,12 @@ void executeCodeBlockActions(ImmutableArray executableCodeBlocks, IE } } - private static ImmutableArray GetSyntaxNodesToAnalyze( + private static void AddSyntaxNodesToAnalyze( SyntaxNode declaredNode, ISymbol declaredSymbol, ImmutableArray declarationsInNode, SemanticModel semanticModel, + ArrayBuilder nodesToAnalyze, CancellationToken cancellationToken) { // Eliminate descendant member declarations within declarations. @@ -2755,7 +2774,7 @@ void executeCodeBlockActions(ImmutableArray executableCodeBlocks, IE break; } - return ImmutableArray.Empty; + return; } // Compute the topmost node representing the syntax declaration for the member that needs to be skipped. @@ -2775,17 +2794,14 @@ void executeCodeBlockActions(ImmutableArray executableCodeBlocks, IE Func? additionalFilter = semanticModel.GetSyntaxNodesToAnalyzeFilter(declaredNode, declaredSymbol); bool shouldAddNode(SyntaxNode node) => (descendantDeclsToSkip == null || !descendantDeclsToSkip.Contains(node)) && (additionalFilter is null || additionalFilter(node)); - var nodeBuilder = ArrayBuilder.GetInstance(); foreach (var node in declaredNode.DescendantNodesAndSelf(descendIntoChildren: shouldAddNode, descendIntoTrivia: true)) { if (shouldAddNode(node) && !semanticModel.ShouldSkipSyntaxNodeAnalysis(node, declaredSymbol)) { - nodeBuilder.Add(node); + nodesToAnalyze.Add(node); } } - - return nodeBuilder.ToImmutableAndFree(); } private static bool IsEquivalentSymbol(ISymbol declaredSymbol, ISymbol? otherSymbol) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs index 035b4f86df0e7..e589c463aca4c 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs @@ -21,7 +21,7 @@ private sealed class AnalyzerExecutionContext /// /// Cached mapping of localizable strings in this descriptor to any exceptions thrown while obtaining them. /// - private static ImmutableSegmentedDictionary s_localizableStringToException = ImmutableSegmentedDictionary.Empty.WithComparer(Roslyn.Utilities.ReferenceEqualityComparer.Instance); + private static ImmutableDictionary s_localizableStringToException = ImmutableDictionary.Empty.WithComparers(Roslyn.Utilities.ReferenceEqualityComparer.Instance); private readonly DiagnosticAnalyzer _analyzer; private readonly object _gate; @@ -345,7 +345,7 @@ void forceLocalizableStringExceptions(LocalizableString localizableString) if (!localizableString.CanThrowExceptions) return null; - return RoslynImmutableInterlocked.GetOrAdd(ref s_localizableStringToException, localizableString, computeException); + return ImmutableInterlocked.GetOrAdd(ref s_localizableStringToException, localizableString, computeException); static Exception? computeException(LocalizableString localizableString) { diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb index adf299521735f..8c734a0c1c4b1 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb @@ -4892,14 +4892,6 @@ lElseClause: getResult = BadExpression(node, ErrorTypeSymbol.UnknownResultType).MakeCompilerGenerated() End If - Dim resultType As TypeSymbol - - If bindAsStatement Then - resultType = GetSpecialType(SpecialType.System_Void, node, diagnostics) - Else - resultType = getResult.Type - End If - If Not hasErrors Then diagnostics.AddRange(allIgnoreDiagnostics) End If @@ -4909,7 +4901,7 @@ lElseClause: Return New BoundAwaitOperator(node, operand, awaitableInstancePlaceholder, getAwaiter, awaiterInstancePlaceholder, isCompleted, getResult, - resultType, hasErrors) + type:=getResult.Type, hasErrors) End Function Private Shared Function DiagnosticBagHasErrorsOtherThanObsoleteOnes(bag As DiagnosticBag) As Boolean diff --git a/src/Compilers/VisualBasic/Portable/BoundTree/BoundAwaitOperator.vb b/src/Compilers/VisualBasic/Portable/BoundTree/BoundAwaitOperator.vb index 98630db3ca47b..97a61ebf5c827 100644 --- a/src/Compilers/VisualBasic/Portable/BoundTree/BoundAwaitOperator.vb +++ b/src/Compilers/VisualBasic/Portable/BoundTree/BoundAwaitOperator.vb @@ -2,17 +2,13 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. -Imports Microsoft.CodeAnalysis.Text -Imports Microsoft.CodeAnalysis.VisualBasic.Symbols -Imports Microsoft.CodeAnalysis.VisualBasic.Syntax - Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend Class BoundAwaitOperator #If DEBUG Then Private Sub Validate() - Debug.Assert(Type.Equals(GetResult.Type) OrElse Type.SpecialType = SpecialType.System_Void) + Debug.Assert(Type.Equals(GetResult.Type)) End Sub #End If diff --git a/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.vb b/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.vb index f31df66a0aa53..b22483b08f3b6 100644 --- a/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.vb +++ b/src/Compilers/VisualBasic/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.vb @@ -105,8 +105,8 @@ Class C End Class]]>.Value Dim expectedOperationTree = .Value @@ -134,8 +134,8 @@ Class C End Class]]>.Value Dim expectedOperationTree = .Value @@ -162,8 +162,8 @@ Class C End Class]]>.Value Dim expectedOperationTree = .Value @@ -211,5 +211,115 @@ BC30800: Method arguments must be enclosed in parentheses. VerifyOperationTreeAndDiagnosticsForTest(Of ExpressionStatementSyntax)(source, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True) End Sub + + + + Public Sub TestAwaitExpression_InStatement() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of AwaitExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True) + End Sub + + + + Public Sub TestAwaitExpression_InStatement_InSubLambda() + Dim source = + + + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of AwaitExpressionSyntax)(source.Value, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True) + CompileAndVerify(source, expectedOutput:="M2", useLatestFramework:=True) + End Sub + + + + Public Sub TestAwaitExpression_InStatement_InSubWithExpressionLambda() + Dim source = + + + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of AwaitExpressionSyntax)(source.Value, expectedOperationTree, expectedDiagnostics, useLatestFramework:=True) + CompileAndVerify(source, expectedOutput:="M2", useLatestFramework:=True) + End Sub End Class End Namespace diff --git a/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs b/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs index df82f53ae1552..bf108cfaf189c 100644 --- a/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs +++ b/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs @@ -19,52 +19,73 @@ internal static class SegmentedArrayHelper [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetSegmentSize() { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 4 => 16384, + 8 => 8192, + 12 => 4096, + 16 => 4096, + 24 => 2048, + 28 => 2048, + 32 => 2048, + 40 => 2048, #if NETCOREAPP3_0_OR_NEWER - return InlineCalculateSegmentSize(Unsafe.SizeOf()); + _ => InlineCalculateSegmentSize(Unsafe.SizeOf()), #else - if (Unsafe.SizeOf() == Unsafe.SizeOf()) - { - return ReferenceTypeSegmentHelper.SegmentSize; - } - else - { - return ValueTypeSegmentHelper.SegmentSize; - } + _ => FallbackSegmentHelper.SegmentSize, #endif + }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetSegmentShift() { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 4 => 14, + 8 => 13, + 12 => 12, + 16 => 12, + 24 => 11, + 28 => 11, + 32 => 11, + 40 => 11, #if NETCOREAPP3_0_OR_NEWER - return InlineCalculateSegmentShift(Unsafe.SizeOf()); + _ => InlineCalculateSegmentShift(Unsafe.SizeOf()), #else - if (Unsafe.SizeOf() == Unsafe.SizeOf()) - { - return ReferenceTypeSegmentHelper.SegmentShift; - } - else - { - return ValueTypeSegmentHelper.SegmentShift; - } + _ => FallbackSegmentHelper.SegmentShift, #endif + }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetOffsetMask() { + return Unsafe.SizeOf() switch + { + // Hard code common values since not all versions of the .NET JIT support reducing this computation to a + // constant value at runtime. Values are validated against the reference implementation in + // CalculateSegmentSize in unit tests. + 4 => 16383, + 8 => 8191, + 12 => 4095, + 16 => 4095, + 24 => 2047, + 28 => 2047, + 32 => 2047, + 40 => 2047, #if NETCOREAPP3_0_OR_NEWER - return InlineCalculateOffsetMask(Unsafe.SizeOf()); + _ => InlineCalculateOffsetMask(Unsafe.SizeOf()), #else - if (Unsafe.SizeOf() == Unsafe.SizeOf()) - { - return ReferenceTypeSegmentHelper.OffsetMask; - } - else - { - return ValueTypeSegmentHelper.OffsetMask; - } + _ => FallbackSegmentHelper.OffsetMask, #endif + }; } /// @@ -94,7 +115,7 @@ private static int CalculateSegmentSize(int elementSize) static int ArraySize(int elementSize, int segmentSize) { // Array object header, plus space for the elements - return (2 * IntPtr.Size) + (elementSize * segmentSize); + return (2 * IntPtr.Size + 8) + (elementSize * segmentSize); } } @@ -141,7 +162,7 @@ private static int InlineCalculateSegmentShift(int elementSize) // Default Large Object Heap size threshold // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111 const uint Threshold = 85000; - return System.Numerics.BitOperations.Log2((uint)((Threshold / elementSize) - (2 * Unsafe.SizeOf()))); + return System.Numerics.BitOperations.Log2((uint)((Threshold / elementSize) - (2 * Unsafe.SizeOf() + 8))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -156,25 +177,20 @@ internal static class TestAccessor public static int CalculateSegmentSize(int elementSize) => SegmentedArrayHelper.CalculateSegmentSize(elementSize); - public static int CalculateSegmentShift(int elementSize) - => SegmentedArrayHelper.CalculateSegmentShift(elementSize); - - public static int CalculateOffsetMask(int elementSize) - => SegmentedArrayHelper.CalculateOffsetMask(elementSize); - } + public static int CalculateSegmentShift(int segmentSize) + => SegmentedArrayHelper.CalculateSegmentShift(segmentSize); - private static class ReferenceTypeSegmentHelper - { - public static readonly int SegmentSize = CalculateSegmentSize(Unsafe.SizeOf()); - public static readonly int SegmentShift = CalculateSegmentShift(SegmentSize); - public static readonly int OffsetMask = CalculateOffsetMask(SegmentSize); + public static int CalculateOffsetMask(int segmentSize) + => SegmentedArrayHelper.CalculateOffsetMask(segmentSize); } - private static class ValueTypeSegmentHelper +#if !NETCOREAPP3_0_OR_NEWER + private static class FallbackSegmentHelper { public static readonly int SegmentSize = CalculateSegmentSize(Unsafe.SizeOf()); public static readonly int SegmentShift = CalculateSegmentShift(SegmentSize); public static readonly int OffsetMask = CalculateOffsetMask(SegmentSize); } +#endif } } diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs index 4a56e56c60971..edbb12f04cb40 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs @@ -234,7 +234,7 @@ public void Update_Leaf_GenericMethod() var src1 = @" class C { - static void Main(string[] args) + static void Main() { Swap(5,6); } @@ -247,12 +247,9 @@ static void Main(string[] args) var src2 = @" class C { - static void Main(string[] args) + static void Main() { - while (true) - { - Swap(5,6); - } + Swap(5,6); } static void Swap(T lhs, T rhs) where T : System.IComparable @@ -264,8 +261,15 @@ static void Main(string[] args) var edits = GetTopEdits(src1, src2); var active = GetActiveStatements(src1, src2); - edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericMethodUpdate, "static void Swap(T lhs, T rhs)")); + edits.VerifySemanticDiagnostics( + active, + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static void Swap(T lhs, T rhs)", GetResource("method")) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics( + active, + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Swap"), preserveLocalVariables: true) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } // Async @@ -762,52 +766,53 @@ public void Update_Leaf_Indexers1() var src1 = @" class Test { - static void Main(string[] args) + static void Main() { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + c[0] = 1; } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[i]; } - set { arr[i] = value; } + get => 0; + set { value = i; } } }"; var src2 = @" class Test { - static void Main(string[] args) + static void Main() { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + c[0] = 1; } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[i]; } - set { arr[i+1] = value; } + get => 0; + set { value = i + 1; } } }"; var edits = GetTopEdits(src1, src2); var active = GetActiveStatements(src1, src2); edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericTypeUpdate, "set")); + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "set", GetResource("indexer setter")) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics(active, + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/750244")] - public void Update_Inner_Indexers1() + public void Update_Inner_Indexers_Setter() { var src1 = @" using System; @@ -856,58 +861,58 @@ class SampleCollection // Rude edits of active statements (AS:1) are not reported if the top-level edits are rude. edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericTypeUpdate, "set"), Diagnostic(RudeEditKind.ActiveStatementUpdate, "stringCollection[1] = \"hello\";")); } [Fact] - public void Update_Leaf_Indexers2() + public void Update_Leaf_Indexers_Getter() { var src1 = @" class Test { - static void Main(string[] args) + static void Main() { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + Console.WriteLine(c[0]); } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[i]; } - set { arr[i] = value; } + get { return 0; } + set { } } }"; var src2 = @" class Test { - static void Main(string[] args) + static void Main() { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + Console.WriteLine(c[0]); } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[0]; } - set { arr[i] = value; } + get { return 1; } + set { } } }"; var edits = GetTopEdits(src1, src2); var active = GetActiveStatements(src1, src2); edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericTypeUpdate, "get")); + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "get", GetResource("indexer getter")) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics(active, + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/750244")] @@ -958,50 +963,45 @@ class SampleCollection // Rude edits of active statements (AS:1) are not reported if the top-level edits are rude. edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericTypeUpdate, "get"), Diagnostic(RudeEditKind.ActiveStatementUpdate, "Console.WriteLine(stringCollection[1]);")); } [Fact] - public void Deleted_Leaf_Indexers1() + public void Deleted_Leaf_Indexers_Setter() { var src1 = @" class Test { - static void Main(string[] args) + static void Main() { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + c[0] = 1; } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[i]; } - set { arr[i] = value; } + get => 0; + set { throw null; } } }"; var src2 = @" class Test { - static void Main(string[] args) + static void Main() { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + c[0] = 1; } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[i]; } + get => 0; set { } } }"; @@ -1009,11 +1009,16 @@ class SampleCollection var active = GetActiveStatements(src1, src2); edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericTypeUpdate, "set")); + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "set", GetResource("indexer setter")) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics(active, + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] - public void Deleted_Inner_Indexers1() + public void Deleted_Inner_Indexers_Setter() { var src1 = @" class Test @@ -1062,26 +1067,24 @@ class SampleCollection } [Fact] - public void Deleted_Leaf_Indexers2() + public void Deleted_Leaf_Indexers_Getter() { var src1 = @" class Test { static void Main(string[] args) { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + Console.WriteLine(c[0]); } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { - get { return arr[i]; } - set { arr[i] = value; } + get { return 1; } + set { } } }"; var src2 = @" @@ -1089,30 +1092,33 @@ class Test { static void Main(string[] args) { - SampleCollection stringCollection = new SampleCollection(); - stringCollection[0] = ""hello""; - Console.WriteLine(stringCollection[0]); + var c = new C(); + Console.WriteLine(c[0]); } } -class SampleCollection +class C { - private T[] arr = new T[100]; public T this[int i] { get { } - set { arr[i] = value; } + set { } } }"; var edits = GetTopEdits(src1, src2); var active = GetActiveStatements(src1, src2); edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.GenericTypeUpdate, "get")); + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "get", GetResource("indexer getter")) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics(active, + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] - public void Deleted_Inner_Indexers2() + public void Deleted_Inner_Indexers_Getter() { var src1 = @" class Test diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs index 8129cb0d9bf27..75363f78d29ba 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs @@ -500,9 +500,16 @@ static void Bar() }"; var edits = GetTopEdits(src1, src2); + + edits.VerifyLineEdits( + Array.Empty(), + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "\r\n /*edit*/", FeaturesResources.method) }, + capabilities: EditAndContinueCapabilities.Baseline); + edits.VerifyLineEdits( Array.Empty(), - diagnostics: new[] { Diagnostic(RudeEditKind.GenericTypeTriviaUpdate, "\r\n /*edit*/", FeaturesResources.method) }); + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -529,7 +536,13 @@ static void Bar() var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - diagnostics: new[] { Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, "\r\n ", FeaturesResources.method) }); + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "\r\n ", FeaturesResources.method) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifyLineEdits( + Array.Empty(), + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -875,7 +888,13 @@ public C(int a) var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - diagnostics: new[] { Diagnostic(RudeEditKind.GenericTypeUpdate, "public C(int a)") }); + diagnostics: new[] { Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "public C(int a)", GetResource("constructor")) }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifyLineEdits( + Array.Empty(), + semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } #endregion @@ -1249,7 +1268,7 @@ class C } [Fact] - public void Field_RudeRecompile2() + public void Field_RudeRecompile1() { var src1 = @" class C @@ -1263,12 +1282,22 @@ class C static int Goo = 1 + 1; }"; var edits = GetTopEdits(src1, src2); + edits.VerifyLineEdits( Array.Empty(), diagnostics: new[] { - Diagnostic(RudeEditKind.GenericTypeUpdate, "class C") - }); + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "class C", GetResource("static constructor", "C()")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifyLineEdits( + Array.Empty(), + semanticEdits: new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -2008,19 +2037,29 @@ public void LineMapping_FileChange_RudeEdit() { var src1 = @" #line 1 ""a"" -class C { static void Bar() { } } +class C { static void F() { } } "; var src2 = @" #line 1 ""b"" -class C { static void Bar() { } }"; +class C { static void F() { } }"; var edits = GetTopEdits(src1, src2); + edits.VerifyLineEdits( Array.Empty(), diagnostics: new[] { - Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, "{", FeaturesResources.method) - }); + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "{", GetResource("method")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifyLineEdits( + Array.Empty(), + semanticEdits: new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } #endregion diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs index 561762c7b8147..aceec048675f9 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs @@ -2143,6 +2143,121 @@ void F() capabilities: EditAndContinueCapabilities.Baseline); } + [Fact] + public void Lambdas_Insert_First_Static_InGenericContext_Method() + { + var src1 = @" +using System; +class C +{ + void F() + { + } +}"; + var src2 = @" +using System; +class C +{ + void F() + { + var f = new Func(a => a); + } +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.NewTypeDefinition | + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.AddStaticFieldToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] { Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda")) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + } + + [Fact] + public void Lambdas_Insert_First_Static_InGenericContext_Type() + { + var src1 = @" +using System; +class C +{ + void F() + { + } +}"; + var src2 = @" +using System; +class C +{ + void F() + { + var f = new Func(a => a); + } +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.NewTypeDefinition | + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.AddStaticFieldToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] { Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda")) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + } + + [Fact] + public void Lambdas_Insert_First_Static_InGenericContext_LocalFunction() + { + var src1 = @" +using System; +class C +{ + void F() + { + void L() + { + } + } +}"; + var src2 = @" +using System; +class C +{ + void F() + { + void L() + { + var f = new Func(a => a); + } + } +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.NewTypeDefinition | + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] { Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda")) }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + } + [Fact] public void Lambdas_Insert_Static_Nested() { @@ -5329,6 +5444,141 @@ void F() capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } + [Fact] + public void LocalFunctions_Insert_Static_InGenericContext_Method() + { + var src1 = @" +using System; + +class C +{ + void F() + { + } +} +"; + var src2 = @" +using System; + +class C +{ + void F() + { + int f(int a) => a; + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "f", GetResource("local function")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + } + + [Fact] + public void LocalFunctions_Insert_Static_InGenericContext_Type() + { + var src1 = @" +using System; + +class C +{ + void F() + { + } +} +"; + var src2 = @" +using System; + +class C +{ + void F() + { + int f(int a) => a; + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "f", GetResource("local function")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + } + + [Fact] + public void LocalFunctions_Insert_Static_InGenericContext_LocalFunction() + { + var src1 = @" +using System; + +class C +{ + void F() + { + void L() + { + void M() + { + } + } + } +} +"; + var src2 = @" +using System; + +class C +{ + void F() + { + void L() + { + void M() + { + int f(int a) => a; + } + } + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "L", GetResource("local function")), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "f", GetResource("local function")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + } + [Fact] public void LocalFunctions_Insert_Static_Nested_ExpressionBodies() { @@ -7179,6 +7429,45 @@ int f1(int a1) Diagnostic(RudeEditKind.CapturingVariable, "a1", "a1")); } + [Fact] + public void LocalFunctions_Update_Generic() + { + var src1 = @" +class C +{ + void F() + { + int L() => 1; + int M() => 1; + int N() => 1; + int O() => 1; + } +}"; + var src2 = @" +class C +{ + void F() + { + int L() => 1; + int M() => 2; + int N() => 1 ; + int O() => 1; + } +}"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "M", GetResource("local function")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemanticDiagnostics( + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")] public void LocalFunctions_RenameCapturedLocal() { @@ -9476,7 +9765,10 @@ IEnumerable F() "; var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType); + capabilities: + EditAndContinueCapabilities.NewTypeDefinition | + EditAndContinueCapabilities.AddStaticFieldToExistingType | + EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( new[] @@ -9674,6 +9966,129 @@ static IEnumerable F() capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } + [Fact] + public void Yield_Update_GenericType() + { + var src1 = @" +class C +{ + static IEnumerable F() + { + yield return 1; + } +} +"; + var src2 = @" +class C +{ + static IEnumerable F() + { + yield return 2; + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static IEnumerable F()", GetResource("method")) + }, + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + } + + [Fact] + public void Yield_Update_GenericMethod() + { + var src1 = @" +class C +{ + static IEnumerable F() + { + yield return 1; + } +} +"; + var src2 = @" +class C +{ + static IEnumerable F() + { + yield return 2; + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static IEnumerable F()", GetResource("method")) + }, + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + } + + [Fact] + public void Yield_Update_GenericLocalFunction() + { + var src1 = @" +class C +{ + void F() + { + IEnumerable L() + { + yield return 1; + } + } +} +"; + var src2 = @" +class C +{ + void F() + { + IEnumerable L() + { + yield return 2; + } + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "L", GetResource("local function")) + }, + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + } + [Fact] public void MissingIteratorStateMachineAttribute() { @@ -10493,7 +10908,136 @@ static async IAsyncEnumerable F() } [Fact] - public void MissingAsyncStateMachineAttribute1() + public void Await_Update_GenericType() + { + var src1 = @" +class C +{ + static async Task F() + { + await Task.FromResult(1); + } +} +"; + var src2 = @" +class C +{ + static async Task F() + { + await Task.FromResult(2); + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static async Task F()", GetResource("method")) + }, + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + } + + [Fact] + public void Await_Update_GenericMethod() + { + var src1 = @" +class C +{ + static async Task F() + { + await Task.FromResult(1); + } +} +"; + var src2 = @" +class C +{ + static async Task F() + { + await Task.FromResult(2); + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static async Task F()", GetResource("method")) + }, + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + } + + [Fact] + public void Await_Update_GenericLocalFunction() + { + var src1 = @" +class C +{ + void F() + { + void M() + { + async Task L() + { + await Task.FromResult(1); + } + } + } +} +"; + var src2 = @" +class C +{ + void F() + { + void M() + { + async Task L() + { + await Task.FromResult(2); + } + } + } +} +"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "L", GetResource("local function")) + }, + capabilities: + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.AddInstanceFieldToExistingType); + } + + [Fact] + public void MissingAsyncStateMachineAttribute() { var src1 = @" using System.Threading.Tasks; diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs index 7140773c06edc..308d5ecf2643e 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs @@ -2009,41 +2009,152 @@ interface I } [Fact] - public void Type_Generic_InsertMembers() + public void Type_Generic_Insert_StatelessMembers() { var src1 = @" using System; class C { + int P1 { get => 1; } + int this[string s] { set {} } } "; var src2 = @" using System; class C { + C(int x) {} + void M() {} - int P1 { get; set; } + void G() {} + int P1 { get => 1; set {} } int P2 { get => 1; set {} } - int this[int i] { get => 1; set {} } + int this[int i] { set {} get => 1; } + int this[string s] { set {} get => 1; } event Action E { add {} remove {} } - event Action EF; - int F1, F2; enum E {} interface I {} + interface I {} class D {} + class D {} + delegate void Del(); + delegate void Del(); } "; var edits = GetTopEdits(src1, src2); + + var diagnostics = new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "C(int x)", FeaturesResources.constructor), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "void M()", FeaturesResources.method), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "void G()", FeaturesResources.method), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int P2", FeaturesResources.property_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int this[int i]", FeaturesResources.indexer_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "event Action E", FeaturesResources.event_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "set", CSharpFeaturesResources.property_setter), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "get", CSharpFeaturesResources.indexer_getter), + }; + + edits.VerifySemanticDiagnostics(diagnostics, capabilities: EditAndContinueCapabilities.AddMethodToExistingType); + edits.VerifySemanticDiagnostics(diagnostics, capabilities: EditAndContinueCapabilities.GenericAddMethodToExistingType); + edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "void M()", GetResource("method")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int P1", GetResource("auto-property")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int P2", GetResource("property")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int this[int i]", GetResource("indexer")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "event Action E", "event"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "EF", "event field"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F1", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F2", GetResource("field"))); + capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.GenericAddMethodToExistingType); + } + + [Fact] + public void Type_Generic_Insert_DataMembers() + { + var src1 = @" +using System; +class C +{ +} +"; + var src2 = @" +using System; +class C +{ + int P { get; set; } + event Action EF; + int F1, F2; + static int SF; +} +"; + var edits = GetTopEdits(src1, src2); + + var nonGenericCapabilities = + EditAndContinueCapabilities.AddInstanceFieldToExistingType | + EditAndContinueCapabilities.AddStaticFieldToExistingType | + EditAndContinueCapabilities.AddMethodToExistingType; + + edits.VerifySemanticDiagnostics(new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int P", FeaturesResources.auto_property), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "EF", CSharpFeaturesResources.event_field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F1", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F2", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "SF", FeaturesResources.field), + }, capabilities: nonGenericCapabilities); + + edits.VerifySemanticDiagnostics(new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F1", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F2", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "SF", FeaturesResources.field), + }, capabilities: nonGenericCapabilities | EditAndContinueCapabilities.GenericAddMethodToExistingType); + + edits.VerifySemanticDiagnostics(new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "int P", FeaturesResources.auto_property), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "EF", CSharpFeaturesResources.event_field) + }, capabilities: nonGenericCapabilities | EditAndContinueCapabilities.GenericAddFieldToExistingType); + + edits.VerifySemanticDiagnostics( + capabilities: nonGenericCapabilities | EditAndContinueCapabilities.GenericAddMethodToExistingType | EditAndContinueCapabilities.GenericAddFieldToExistingType); + } + + [Fact] + public void Type_Generic_Insert_IntoNestedType() + { + var src1 = @" +class C +{ + class D + { + } +} +"; + var src2 = @" +class C +{ + class D + { + void F() {} + int X; + static int Y; + } +} +"; + var edits = GetTopEdits(src1, src2); + + var nonGenericCapabilities = + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.AddInstanceFieldToExistingType | + EditAndContinueCapabilities.AddStaticFieldToExistingType; + + edits.VerifySemanticDiagnostics(new[] + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "void F()", FeaturesResources.method), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "X", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Y", FeaturesResources.field) + }, capabilities: nonGenericCapabilities); + + edits.VerifySemanticDiagnostics(capabilities: + nonGenericCapabilities | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericAddFieldToExistingType); } [Fact] @@ -2100,11 +2211,28 @@ interface I { void F() {} } DocumentResults( diagnostics: new[] { - Diagnostic(RudeEditKind.GenericTypeUpdate, "void F()"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "void F()"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "void F()"), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")) }) - }); + }, + capabilities: EditAndContinueCapabilities.Baseline); + + EditAndContinueValidation.VerifySemantics( + new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + new[] + { + DocumentResults(), + + DocumentResults( + semanticEdits: new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("S.F")), + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I.F")) + }) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/54881")] @@ -5533,7 +5661,7 @@ public void Type_Partial_InsertDeleteAndChange_Constraint() DocumentResults( diagnostics: new[] { - Diagnostic(RudeEditKind.ChangingConstraints, "where T : new()", FeaturesResources.type_parameter) + Diagnostic(RudeEditKind.ChangingConstraints, "where T : new()", GetResource("type parameter")) }), DocumentResults(), @@ -6438,6 +6566,18 @@ public void PartialMember_DeleteInsert_GenericMethod() var srcA2 = "partial class C { }"; var srcB2 = "partial class C { void F() {} }"; + EditAndContinueValidation.VerifySemantics( + new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + new[] + { + DocumentResults(), + DocumentResults(semanticEdits: new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) + }) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + EditAndContinueValidation.VerifySemantics( new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, new[] @@ -6445,9 +6585,10 @@ public void PartialMember_DeleteInsert_GenericMethod() DocumentResults(), DocumentResults(diagnostics: new[] { - Diagnostic(RudeEditKind.GenericMethodUpdate, "void F()") + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")) }) - }); + }, + capabilities: EditAndContinueCapabilities.Baseline); } [Fact] @@ -6458,6 +6599,18 @@ public void PartialMember_DeleteInsert_GenericType() var srcA2 = "partial class C { }"; var srcB2 = "partial class C { void F() {} }"; + EditAndContinueValidation.VerifySemantics( + new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + new[] + { + DocumentResults(), + DocumentResults(semanticEdits: new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) + }) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + EditAndContinueValidation.VerifySemantics( new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, new[] @@ -6465,9 +6618,10 @@ public void PartialMember_DeleteInsert_GenericType() DocumentResults(), DocumentResults(diagnostics: new[] { - Diagnostic(RudeEditKind.GenericTypeUpdate, "void F()") + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method")) }) - }); + }, + capabilities: EditAndContinueCapabilities.Baseline); } [Fact] @@ -6762,17 +6916,18 @@ public void PartialMember_DeleteInsert_MethodAddTypeParameter() new[] { DocumentResults( - diagnostics: new[] + semanticEdits: new[] { - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "void F()", GetResource("method")) + SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetArity() == 1)?.ISymbol) }), DocumentResults( semanticEdits: new[] { - SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetMemberTypeParameters().Length == 0)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("S")) + SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetArity() == 0)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("S")) }), - }); + }, + capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.GenericAddMethodToExistingType); } #endregion @@ -8080,6 +8235,102 @@ static void EntryPoint(string[] args) capabilities: EditAndContinueCapabilities.Baseline); } + [Fact] + public void Method_Rename_GenericType() + { + var src1 = @" +class C +{ + static void F() + { + } +}"; + var src2 = @" +class C +{ + static void G() + { + } +}"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "static void G()", FeaturesResources.method) + }, + capabilities: EditAndContinueCapabilities.AddMethodToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "static void G()", FeaturesResources.method) + }, + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")), + SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.G")) + }, + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + } + + [Fact] + public void Method_Rename_GenericMethod() + { + var src1 = @" +class C +{ + static void F() + { + } +}"; + var src2 = @" +class C +{ + static void G() + { + } +}"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "static void G()", GetResource("method")) + }, + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "static void G()", GetResource("method")) + }, + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")), + SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.G")) + }, + capabilities: + EditAndContinueCapabilities.AddMethodToExistingType | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + } + [Theory] [InlineData("virtual")] [InlineData("abstract")] @@ -8201,6 +8452,43 @@ public async Task WaitAsync() capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } + [Fact] + public void MethodUpdate_AsyncMethod_Generic() + { + var src1 = @" +class C +{ + public async Task F() + { + await Task.FromResult(1); + } +}"; + var src2 = @" +class C +{ + public async Task F() + { + await Task.FromResult(2); + } +}"; + var edits = GetTopEdits(src1, src2); + + edits.VerifySemanticDiagnostics( + capabilities: + EditAndContinueCapabilities.AddInstanceFieldToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingStateMachineMethodNotSupportedByRuntime, "public async Task F()"), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "public async Task F()", GetResource("method")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "public async Task F()", GetResource("method")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + } + [Fact] public void MethodUpdate_AddReturnTypeAttribute() { @@ -9872,7 +10160,18 @@ class C "Update [public C(int a) : base(a) { }]@21 -> [public C(int a) { }]@21"); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "public C(int a)")); + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "public C(int a)", GetResource("constructor")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) + }, + capabilities: EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -9915,7 +10214,18 @@ class C "Update [public C(int a) : base(a) { }]@21 -> [public C(int a) : base(a + 1) { }]@21"); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "public C(int a)")); + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "public C(int a)", GetResource("constructor")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) + }, + capabilities: EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/743552")] @@ -11894,8 +12204,19 @@ public void FieldInitializerUpdate_GenericType() "Update [a = 1]@17 -> [a = 2]@17"); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "a = 2"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "class C")); + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "a = 2", GetResource("field")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "class C", GetResource("constructor", "C()")) + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) + }, + capabilities: EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -11907,8 +12228,19 @@ public void PropertyInitializerUpdate_GenericType() var edits = GetTopEdits(src1, src2); edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "int a"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "class C")); + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "int a", GetResource("property")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "class C", GetResource("constructor", "C()")), + }, + capabilities: EditAndContinueCapabilities.Baseline); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -15917,28 +16249,6 @@ class C capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } - [Fact] - public void Indexer_AddSetAccessor_GenericType() - { - var src1 = @" -class C -{ - public T this[int i] { get { return default; } } -}"; - var src2 = @" -class C -{ - public T this[int i] { get { return default; } set { } } -}"; - var edits = GetTopEdits(src1, src2); - - edits.VerifyEdits("Insert [set { }]@68"); - - edits.VerifySemanticDiagnostics( - new[] { Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "set", GetResource("indexer setter")) }, - capabilities: EditAndContinueCapabilities.AddMethodToExistingType); - } - [Fact] public void Indexer_Delete() { @@ -17047,6 +17357,42 @@ public void Parameter_Reorder_Rename() capabilities: EditAndContinueCapabilities.Baseline); } + [Fact] + public void Parameter_Reorder_Rename_Generic() + { + var src1 = @"class C { public void M(int a, int b) {} }"; + var src2 = @"class C { public void M(int b, int c) {} } "; + + var edits = GetTopEdits(src1, src2); + + edits.VerifySemantics( + new[] + { + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) + }, + capabilities: + EditAndContinueCapabilities.UpdateParameters | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "int b", GetResource("method")), + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "int b", GetResource("parameter")), + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "int c", GetResource("parameter")) + }, + capabilities: EditAndContinueCapabilities.GenericAddMethodToExistingType); + + edits.VerifySemanticDiagnostics( + new[] + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "int b", FeaturesResources.parameter), + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "int c", FeaturesResources.parameter) + }, + capabilities: EditAndContinueCapabilities.GenericUpdateMethod); + } + [Fact] public void Parameter_Type_Update() { @@ -17460,11 +17806,8 @@ public void MethodTypeParameter_Attribute_Insert1() "Update [T]@75 -> [[A]T]@72"); edits.VerifySemanticDiagnostics( - new[] - { - Diagnostic(RudeEditKind.GenericMethodUpdate, "T"), - }, - capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); + new[] { Diagnostic(RudeEditKind.GenericMethodUpdate, "T") }, + capabilities: EditAndContinueCapabilities.ChangeCustomAttributes | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -17482,11 +17825,8 @@ public void MethodTypeParameter_Attribute_Insert2() "Update [[A ]T]@120 -> [[A, B]T]@120"); edits.VerifySemanticDiagnostics( - new[] - { - Diagnostic(RudeEditKind.GenericMethodUpdate, "T") - }, - capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); + new[] { Diagnostic(RudeEditKind.GenericMethodUpdate, "T") }, + capabilities: EditAndContinueCapabilities.ChangeCustomAttributes | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -17507,7 +17847,7 @@ public void MethodTypeParameter_Attribute_Delete() { Diagnostic(RudeEditKind.GenericMethodUpdate, "T") }, - capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); + capabilities: EditAndContinueCapabilities.ChangeCustomAttributes | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -17529,7 +17869,7 @@ public void MethodTypeParameter_Attribute_Update_NotSupportedByRuntime() { Diagnostic(RudeEditKind.GenericMethodUpdate, "T") }, - capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); + capabilities: EditAndContinueCapabilities.ChangeCustomAttributes | EditAndContinueCapabilities.GenericUpdateMethod); } [Fact] @@ -17567,7 +17907,7 @@ public void MethodTypeParameter_Attribute_Update_WithBodyUpdate() edits.VerifySemanticDiagnostics( new[] { - Diagnostic(RudeEditKind.GenericMethodUpdate, "void F<[A(1)]T>(T a)"), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F<[A(1)]T>(T a)", GetResource("method")), Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "T", GetResource("type parameter")) }, capabilities: EditAndContinueCapabilities.Baseline); diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index 0f48b69427280..eb45d18126e90 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -36,6 +36,8 @@ using System.Diagnostics; using System.IO; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing; #if !CODE_STYLE using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; @@ -320,12 +322,35 @@ private TestParameters WithScriptOptions(TestParameters parameters) protected abstract Task> GetDiagnosticsWorkerAsync( TestWorkspace workspace, TestParameters parameters); + internal abstract Task GetCodeRefactoringAsync(TestWorkspace workspace, TestParameters parameters); + protected Task TestSmartTagTextAsync(string initialMarkup, string displayText, int index) => TestSmartTagTextAsync(initialMarkup, displayText, new TestParameters(index: index)); protected Task TestSmartTagGlyphTagsAsync(string initialMarkup, ImmutableArray glyphTags, int index) => TestSmartTagGlyphTagsAsync(initialMarkup, glyphTags, new TestParameters(index: index)); + protected async Task TestCodeRefactoringApplicableTextSpan( + string markup, + string textSpanMarker, + TestParameters parameters = null) + { + var ps = parameters ?? TestParameters.Default; + using var workspace = CreateWorkspaceFromOptions(markup, ps); + var refactoring = await GetCodeRefactoringAsync(workspace, ps).ConfigureAwait(false); + + TestFileMarkupParser.GetPositionsAndSpans(markup, out _, out _, out var spans); + Assert.True(spans.ContainsKey(textSpanMarker)); + + var expectedTextSpans = spans[textSpanMarker].Sort(); + var actualTextSpans = refactoring.CodeActions.WhereAsArray(action => action.applicableToSpan is not null).SelectAsArray(action => action.applicableToSpan).Sort(); + Assert.Equal(expectedTextSpans.Length, actualTextSpans.Length); + for (var i = 0; i < expectedTextSpans.Length; i++) + { + Assert.Equal(expectedTextSpans[i], actualTextSpans[i]); + } + } + protected async Task TestSmartTagTextAsync( string initialMarkup, string displayText, diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs index 5cb3bd94770fe..f48a7fd6f2504 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs @@ -92,7 +92,7 @@ public abstract partial class AbstractCodeActionTest : AbstractCodeActionOrUserD protected override Task> GetDiagnosticsWorkerAsync(TestWorkspace workspace, TestParameters parameters) => SpecializedTasks.EmptyImmutableArray(); - internal async Task GetCodeRefactoringAsync( + internal override async Task GetCodeRefactoringAsync( TestWorkspace workspace, TestParameters parameters) { GetDocumentAndSelectSpanOrAnnotatedSpan(workspace, out var document, out var span, out _); diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs index 52ebcccb78bb8..d527047f42c4a 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs @@ -4,6 +4,7 @@ #nullable disable +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -11,8 +12,13 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeFixesAndRefactorings; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.Remote.Testing; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; @@ -20,11 +26,10 @@ using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Remote.Testing; using Xunit.Abstractions; -using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.CodeFixesAndRefactorings; +using FixAllContext = Microsoft.CodeAnalysis.CodeFixes.FixAllContext; +using FixAllProvider = Microsoft.CodeAnalysis.CodeFixes.FixAllProvider; +using FixAllState = Microsoft.CodeAnalysis.CodeFixes.FixAllState; namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics { @@ -85,6 +90,9 @@ protected AbstractUserDiagnosticTest(ITestOutputHelper logger) return dxs; } + internal override Task GetCodeRefactoringAsync(TestWorkspace workspace, TestParameters parameters) + => throw new NotImplementedException("No refactoring provided in diagnostic test"); + protected static void AddAnalyzerToWorkspace(Workspace workspace, DiagnosticAnalyzer analyzer, TestParameters parameters) { AnalyzerReference[] analyzeReferences; diff --git a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs index b1c95da92adef..1492a820d9923 100644 --- a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs +++ b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs @@ -28,6 +28,7 @@ using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; +using Xunit.Sdk; namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeFixes { @@ -192,6 +193,40 @@ public async Task TestGetFixesAsyncForDocumentDiagnosticAnalyzerAsync() Assert.True(documentDiagnosticAnalyzer.ReceivedCallback); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67354")] + public async Task TestGetFixesAsyncForGeneratorDiagnosticAsync() + { + // We have a special GeneratorDiagnosticsPlaceholderAnalyzer that report 0 SupportedDiagnostics. + // We need to ensure that we don't skip this special analyzer + // when computing the diagnostics/code fixes for "Normal" priority bucket, which + // normally only execute those analyzers which report at least one fixable supported diagnostic. + // Note that this special placeholder analyzer instance is always included for the project, + // we do not need to include it in the passed in analyzers. + Assert.Empty(GeneratorDiagnosticsPlaceholderAnalyzer.Instance.SupportedDiagnostics); + + var analyzers = ImmutableArray.Empty; + var generator = new MockAnalyzerReference.MockGenerator(); + var generators = ImmutableArray.Create(generator); + var fixTitle = "Fix Title"; + var codeFix = new MockFixer(fixTitle); + var codeFixes = ImmutableArray.Create(codeFix); + var analyzerReference = new MockAnalyzerReference(codeFixes, analyzers, generators); + + var tuple = ServiceSetup(codeFix, includeConfigurationFixProviders: false); + using var workspace = tuple.workspace; + GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference); + + Assert.False(codeFix.Called); + var fixCollectionSet = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), + priorityProvider: new DefaultCodeActionRequestPriorityProvider(CodeActionRequestPriority.Normal), CodeActionOptions.DefaultProvider, + addOperationScope: _ => null, cancellationToken: CancellationToken.None); + Assert.True(codeFix.Called); + var fixCollection = Assert.Single(fixCollectionSet); + Assert.Equal(MockFixer.Id, fixCollection.FirstDiagnostic.Id); + var fix = Assert.Single(fixCollection.Fixes); + Assert.Equal(fixTitle, fix.Action.Title); + } + [Fact] public async Task TestGetCodeFixWithExceptionInRegisterMethod_Diagnostic() { @@ -395,9 +430,15 @@ private static async Task GetFirstDiagnosticWithFixWithExceptionValidationAsync( internal class MockFixer : CodeFixProvider { public const string Id = "MyDiagnostic"; + private readonly string? _registerFixWithTitle; public bool Called; public int ContextDiagnosticsCount; + public MockFixer(string? registerFixWithTitle = null) + { + _registerFixWithTitle = registerFixWithTitle; + } + public sealed override ImmutableArray FixableDiagnosticIds { get { return ImmutableArray.Create(Id); } @@ -407,6 +448,15 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { Called = true; ContextDiagnosticsCount = context.Diagnostics.Length; + if (_registerFixWithTitle != null) + { + context.RegisterCodeFix( + CodeAction.Create( + _registerFixWithTitle, + createChangedDocument: _ => Task.FromResult(context.Document)), + context.Diagnostics); + } + return Task.CompletedTask; } } @@ -415,14 +465,21 @@ private class MockAnalyzerReference : AnalyzerReference, ICodeFixProviderFactory { public readonly ImmutableArray Fixers; public readonly ImmutableArray Analyzers; + public readonly ImmutableArray Generators; private static readonly ImmutableArray s_defaultFixers = ImmutableArray.Create(new MockFixer()); private static readonly ImmutableArray s_defaultAnalyzers = ImmutableArray.Create(new MockDiagnosticAnalyzer()); - public MockAnalyzerReference(ImmutableArray fixers, ImmutableArray analyzers) + public MockAnalyzerReference(ImmutableArray fixers, ImmutableArray analyzers, ImmutableArray generators) { Fixers = fixers; Analyzers = analyzers; + Generators = generators; + } + + public MockAnalyzerReference(ImmutableArray fixers, ImmutableArray analyzers) + : this(fixers, analyzers, ImmutableArray.Empty) + { } public MockAnalyzerReference(CodeFixProvider? fixer, ImmutableArray analyzers) @@ -471,6 +528,9 @@ public override ImmutableArray GetAnalyzers(string language) public override ImmutableArray GetAnalyzersForAllLanguages() => ImmutableArray.Empty; + public override ImmutableArray GetGenerators(string language) + => Generators; + public ImmutableArray GetFixers() => Fixers; @@ -555,6 +615,23 @@ public override Task> AnalyzeSemanticsAsync(Document return Task.FromResult(ImmutableArray.Empty); } } + + public class MockGenerator : ISourceGenerator + { + private readonly DiagnosticDescriptor s_descriptor = new(MockFixer.Id, "Title", "Message", "Category", DiagnosticSeverity.Warning, isEnabledByDefault: true); + + public void Initialize(GeneratorInitializationContext context) + { + } + + public void Execute(GeneratorExecutionContext context) + { + foreach (var tree in context.Compilation.SyntaxTrees) + { + context.ReportDiagnostic(Diagnostic.Create(s_descriptor, tree.GetLocation(new TextSpan(0, 1)))); + } + } + } } internal class TestErrorLogger : IErrorLoggerService diff --git a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs index 012ec40a00413..051ab4cf42b2b 100644 --- a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs @@ -83,6 +83,12 @@ private static void ValidateHelpLinkForDiagnostic(string diagnosticId, string he return; } + if (diagnosticId == "EnableGenerateDocumentationFile") + { + Assert.Equal("https://github.com/dotnet/roslyn/issues/41640", helpLinkUri); + return; + } + if (helpLinkUri != $"https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/{diagnosticId.ToLowerInvariant()}") { Assert.True(false, $"Invalid help link for {diagnosticId}"); diff --git a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs index 5dcf82ea88711..9e4cfb71877eb 100644 --- a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs +++ b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs @@ -72,7 +72,7 @@ public EditAndContinueWorkspaceServiceTests() }; } - private TestWorkspace CreateWorkspace(out Solution solution, out EditAndContinueWorkspaceService service, Type[] additionalParts = null) + private TestWorkspace CreateWorkspace(out Solution solution, out EditAndContinueService service, Type[] additionalParts = null) { var workspace = new TestWorkspace(composition: FeaturesTestCompositions.Features.AddParts(additionalParts), solutionTelemetryId: s_solutionTelemetryId); solution = workspace.CurrentSolution; @@ -80,7 +80,7 @@ private TestWorkspace CreateWorkspace(out Solution solution, out EditAndContinue return workspace; } - private TestWorkspace CreateEditorWorkspace(out Solution solution, out EditAndContinueWorkspaceService service, out EditAndContinueLanguageService languageService, Type[] additionalParts = null) + private TestWorkspace CreateEditorWorkspace(out Solution solution, out EditAndContinueService service, out EditAndContinueLanguageService languageService, Type[] additionalParts = null) { var composition = EditorTestCompositions.EditorFeatures .RemoveParts(typeof(MockWorkspaceEventListenerProvider)) @@ -161,16 +161,16 @@ private static SourceText GetAnalyzerConfigText((string key, string value)[] ana return document.Project.Solution; } - private EditAndContinueWorkspaceService GetEditAndContinueService(Workspace workspace) + private EditAndContinueService GetEditAndContinueService(TestWorkspace workspace) { - var service = (EditAndContinueWorkspaceService)workspace.Services.GetRequiredService(); + var service = (EditAndContinueService)workspace.GetService(); var accessor = service.GetTestAccessor(); accessor.SetOutputProvider(project => _mockCompilationOutputsProvider(project)); return service; } private async Task StartDebuggingSessionAsync( - EditAndContinueWorkspaceService service, + EditAndContinueService service, Solution solution, CommittedSolution.DocumentState initialState = CommittedSolution.DocumentState.MatchesBuildOutput, IPdbMatchingSourceTextProvider sourceTextProvider = null) @@ -1617,7 +1617,7 @@ public async Task RudeEdits_DocumentOutOfSync(bool breakMode) diagnostics = await service.GetDocumentDiagnosticsAsync(document2, s_noActiveSpans, CancellationToken.None); AssertEx.Equal(new[] { - "ENC0036: " + FeaturesResources.Modifying_a_generic_method_requires_restarting_the_application, + "ENC0113: " + string.Format(FeaturesResources.Updating_0_within_generic_type_or_method_requires_restarting_the_application_because_is_not_supported_by_the_runtime, FeaturesResources.method), "ENC0021: " + string.Format(FeaturesResources.Adding_0_requires_restarting_the_application, FeaturesResources.type_parameter) }, diagnostics.Select(d => $"{d.Id}: {d.GetMessage()}")); @@ -1645,7 +1645,7 @@ public async Task RudeEdits_DocumentOutOfSync(bool breakMode) { "Debugging_EncSession: SolutionSessionId={00000000-AAAA-AAAA-AAAA-000000000000}|SessionId=1|SessionCount=1|EmptySessionCount=0|HotReloadSessionCount=0|EmptyHotReloadSessionCount=2", "Debugging_EncSession_EditSession: SessionId=1|EditSessionId=2|HadCompilationErrors=False|HadRudeEdits=True|HadValidChanges=False|HadValidInsignificantChanges=False|RudeEditsCount=2|EmitDeltaErrorIdCount=0|InBreakState=True|Capabilities=31|ProjectIdsWithAppliedChanges=", - "Debugging_EncSession_EditSession_RudeEdit: SessionId=1|EditSessionId=2|RudeEditKind=36|RudeEditSyntaxKind=8875|RudeEditBlocking=True", + "Debugging_EncSession_EditSession_RudeEdit: SessionId=1|EditSessionId=2|RudeEditKind=113|RudeEditSyntaxKind=8875|RudeEditBlocking=True", "Debugging_EncSession_EditSession_RudeEdit: SessionId=1|EditSessionId=2|RudeEditKind=21|RudeEditSyntaxKind=8910|RudeEditBlocking=True" }, _telemetryLog); } @@ -1655,7 +1655,7 @@ public async Task RudeEdits_DocumentOutOfSync(bool breakMode) { "Debugging_EncSession: SolutionSessionId={00000000-AAAA-AAAA-AAAA-000000000000}|SessionId=1|SessionCount=0|EmptySessionCount=0|HotReloadSessionCount=1|EmptyHotReloadSessionCount=0", "Debugging_EncSession_EditSession: SessionId=1|EditSessionId=2|HadCompilationErrors=False|HadRudeEdits=True|HadValidChanges=False|HadValidInsignificantChanges=False|RudeEditsCount=2|EmitDeltaErrorIdCount=0|InBreakState=False|Capabilities=31|ProjectIdsWithAppliedChanges=", - "Debugging_EncSession_EditSession_RudeEdit: SessionId=1|EditSessionId=2|RudeEditKind=36|RudeEditSyntaxKind=8875|RudeEditBlocking=True", + "Debugging_EncSession_EditSession_RudeEdit: SessionId=1|EditSessionId=2|RudeEditKind=113|RudeEditSyntaxKind=8875|RudeEditBlocking=True", "Debugging_EncSession_EditSession_RudeEdit: SessionId=1|EditSessionId=2|RudeEditKind=21|RudeEditSyntaxKind=8910|RudeEditBlocking=True" }, _telemetryLog); } diff --git a/src/EditorFeatures/Test/EditAndContinue/RemoteEditAndContinueServiceTests.cs b/src/EditorFeatures/Test/EditAndContinue/RemoteEditAndContinueServiceTests.cs index b0a0dd8a87c61..4ee8e15c17466 100644 --- a/src/EditorFeatures/Test/EditAndContinue/RemoteEditAndContinueServiceTests.cs +++ b/src/EditorFeatures/Test/EditAndContinue/RemoteEditAndContinueServiceTests.cs @@ -50,7 +50,9 @@ public async Task Proxy(TestHost testHost) if (testHost == TestHost.InProcess) { - localComposition = localComposition.AddParts(typeof(MockEditAndContinueWorkspaceService)); + localComposition = localComposition + .AddExcludedPartTypes(typeof(EditAndContinueService)) + .AddParts(typeof(MockEditAndContinueWorkspaceService)); } using var localWorkspace = new TestWorkspace(composition: localComposition); @@ -63,16 +65,17 @@ public async Task Proxy(TestHost testHost) { Assert.Null(clientProvider); - mockEncService = (MockEditAndContinueWorkspaceService)localWorkspace.Services.GetRequiredService(); + mockEncService = (MockEditAndContinueWorkspaceService)localWorkspace.GetService(); } else { Assert.NotNull(clientProvider); clientProvider!.AdditionalRemoteParts = new[] { typeof(MockEditAndContinueWorkspaceService) }; + clientProvider!.ExcludedRemoteParts = new[] { typeof(EditAndContinueService) }; var client = await InProcRemoteHostClient.GetTestClientAsync(localWorkspace); var remoteWorkspace = client.TestData.WorkspaceManager.GetWorkspace(); - mockEncService = (MockEditAndContinueWorkspaceService)remoteWorkspace.Services.GetRequiredService(); + mockEncService = (MockEditAndContinueWorkspaceService)remoteWorkspace.Services.GetRequiredService().Service; } var projectId = ProjectId.CreateNewId(); diff --git a/src/EditorFeatures/TestUtilities/EditAndContinue/EditAndContinueTestHelpers.cs b/src/EditorFeatures/TestUtilities/EditAndContinue/EditAndContinueTestHelpers.cs index 098486e37d069..b47389ed730e3 100644 --- a/src/EditorFeatures/TestUtilities/EditAndContinue/EditAndContinueTestHelpers.cs +++ b/src/EditorFeatures/TestUtilities/EditAndContinue/EditAndContinueTestHelpers.cs @@ -39,7 +39,10 @@ internal abstract class EditAndContinueTestHelpers EditAndContinueCapabilities.UpdateParameters; public const EditAndContinueCapabilities AllRuntimeCapabilities = - Net6RuntimeCapabilities; + Net6RuntimeCapabilities | + EditAndContinueCapabilities.GenericAddMethodToExistingType | + EditAndContinueCapabilities.GenericUpdateMethod | + EditAndContinueCapabilities.GenericAddFieldToExistingType; public abstract AbstractEditAndContinueAnalyzer Analyzer { get; } diff --git a/src/EditorFeatures/TestUtilities/EditAndContinue/MockEditAndContinueWorkspaceService.cs b/src/EditorFeatures/TestUtilities/EditAndContinue/MockEditAndContinueWorkspaceService.cs index 589367f37b34e..4c1f378a9e072 100644 --- a/src/EditorFeatures/TestUtilities/EditAndContinue/MockEditAndContinueWorkspaceService.cs +++ b/src/EditorFeatures/TestUtilities/EditAndContinue/MockEditAndContinueWorkspaceService.cs @@ -16,8 +16,8 @@ namespace Microsoft.CodeAnalysis.EditAndContinue.UnitTests internal delegate void ActionOut(out TArg1 arg); internal delegate void ActionOut(TArg1 arg1, out TArg2 arg2); - [ExportWorkspaceService(typeof(IEditAndContinueWorkspaceService), ServiceLayer.Test), Shared] - internal class MockEditAndContinueWorkspaceService : IEditAndContinueWorkspaceService + [Export(typeof(IEditAndContinueService)), Shared] + internal class MockEditAndContinueWorkspaceService : IEditAndContinueService { public Func, ImmutableArray>>? GetBaseActiveStatementSpansImpl; public Func? GetCurrentActiveStatementPositionImpl; diff --git a/src/EditorFeatures/VisualBasicTest/EditAndContinue/LineEditTests.vb b/src/EditorFeatures/VisualBasicTest/EditAndContinue/LineEditTests.vb index 54131a0bbaa35..bf4f8a1c7b135 100644 --- a/src/EditorFeatures/VisualBasicTest/EditAndContinue/LineEditTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EditAndContinue/LineEditTests.vb @@ -366,9 +366,17 @@ Class C(Of T) End Class " Dim edits = GetTopEdits(src1, src2) + edits.VerifyLineEdits( Array.Empty(Of SequencePointUpdates), - diagnostics:={Diagnostic(RudeEditKind.GenericTypeTriviaUpdate, vbCrLf & " ", FeaturesResources.method)}) + diagnostics:={Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, vbCrLf & " ", FeaturesResources.method)}, + capabilities:=EditAndContinueCapabilities.Baseline) + + edits.VerifyLineEdits( + Array.Empty(Of SequencePointUpdates), + semanticEdits:={SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.Bar"))}, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) + End Sub @@ -392,7 +400,13 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifyLineEdits( Array.Empty(Of SequencePointUpdates), - diagnostics:={Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, vbCrLf & " ", FeaturesResources.method)}) + diagnostics:={Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, vbCrLf & " ", FeaturesResources.method)}, + capabilities:=EditAndContinueCapabilities.Baseline) + + edits.VerifyLineEdits( + Array.Empty(Of SequencePointUpdates), + semanticEdits:={SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.Bar"))}, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub @@ -957,9 +971,22 @@ End Class " Dim edits = GetTopEdits(src1, src2) + edits.VerifyLineEdits( Array.Empty(Of SequencePointUpdates), - diagnostics:={Diagnostic(RudeEditKind.GenericTypeUpdate, "Class C(Of T)")}) + diagnostics:= + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, + capabilities:=EditAndContinueCapabilities.Baseline) + + edits.VerifyLineEdits( + Array.Empty(Of SequencePointUpdates), + semanticEdits:= + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").InstanceConstructors.Single(), preserveLocalVariables:=True) + }, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub @@ -1433,7 +1460,8 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifyLineEdits( Array.Empty(Of SequencePointUpdates)(), - diagnostics:={Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, "Sub Bar(Of T)()", FeaturesResources.method)}) + diagnostics:={Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Sub Bar(Of T)()", FeaturesResources.method)}, + capabilities:=EditAndContinueCapabilities.Baseline) End Sub #End Region diff --git a/src/EditorFeatures/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb b/src/EditorFeatures/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb index fd20975d1fab5..9824d09d8e328 100644 --- a/src/EditorFeatures/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb @@ -1238,16 +1238,25 @@ End Interface Dim src1 = " Imports System Class C(Of T) + ReadOnly Property P1(i As Integer) As Integer + Get + Return 1 + End Get + End Property End Class " Dim src2 = " Imports System Class C(Of T) - Dim F1, F2 As New Object, F3 As Integer, F4 As New Object, F5(1, 2), F6? As Integer + Sub New(x As Integer) + End Sub Sub M() End Sub + Sub G(Of S)() + End Sub + Property P1(i As Integer) As Integer Get Return 1 @@ -1257,13 +1266,14 @@ Class C(Of T) End Property Property P2 As Integer - Property P3 As New Object - - Event E1(sender As Object, e As EventArgs) - - Event E2 As Action + Get + Return 1 + End Get + Set(value As Integer) + End Set + End Property - Custom Event E3 As EventHandler + Custom Event E As EventHandler AddHandler(value As EventHandler) End AddHandler RemoveHandler(value As EventHandler) @@ -1272,8 +1282,6 @@ Class C(Of T) End RaiseEvent End Event - Dim WithEvents WE As Object - Enum N A End Enum @@ -1281,30 +1289,155 @@ Class C(Of T) Interface I End Interface + Interface I(Of S) + End Interface + Class D End Class - Delegate Sub G() + Class D(Of S) + End Class + + Delegate Sub Del() + + Delegate Sub Del(Of S)() +End Class" + Dim edits = GetTopEdits(src1, src2) + + Dim diagnostics = + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub New(x As Integer)", FeaturesResources.constructor), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub M()", FeaturesResources.method), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub G(Of S)()", FeaturesResources.method), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P2", FeaturesResources.property_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E", FeaturesResources.event_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub New(x As Integer)", FeaturesResources.constructor), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Property P1(i As Integer)", GetResource("property")), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Set(value As Integer)", FeaturesResources.property_accessor) + } + + edits.VerifySemanticDiagnostics(diagnostics, capabilities:=EditAndContinueCapabilities.AddMethodToExistingType) + edits.VerifySemanticDiagnostics(diagnostics, capabilities:=EditAndContinueCapabilities.GenericAddMethodToExistingType) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Property P1(i As Integer)", GetResource("property")) + }, capabilities:=EditAndContinueCapabilities.AddMethodToExistingType Or EditAndContinueCapabilities.GenericAddMethodToExistingType) + + End Sub + + + Public Sub Type_Generic_Insert_DataMembers() + Dim src1 = " +Imports System +Class C(Of T) +End Class +" + Dim src2 = " +Imports System +Class C(Of T) + Dim F1, F2 As New Object, F3 As Integer, F4 As New Object, F5(1, 2), F6? As Integer + + Property P2 As Integer + Property P3 As New Object + + Event E1(sender As Object, e As EventArgs) + + Event E2 As Action + + Dim WithEvents WE As Object End Class" Dim edits = GetTopEdits(src1, src2) + Dim nonGenericCapabilities = + EditAndContinueCapabilities.AddInstanceFieldToExistingType Or + EditAndContinueCapabilities.AddStaticFieldToExistingType Or + EditAndContinueCapabilities.AddMethodToExistingType + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P2", FeaturesResources.auto_property), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P3", FeaturesResources.auto_property), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E1(sender As Object, e As EventArgs)", FeaturesResources.event_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E2", FeaturesResources.event_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F1", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F2", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F3 As Integer", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F4 As New Object", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F5(1, 2)", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F6?", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "WE As Object", VBFeaturesResources.WithEvents_field), + Diagnostic(RudeEditKind.InsertVirtual, "WE As Object", VBFeaturesResources.WithEvents_field), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, capabilities:=nonGenericCapabilities) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F1", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F2", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F3 As Integer", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F4 As New Object", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F5(1, 2)", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F6?", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertVirtual, "WE As Object", VBFeaturesResources.WithEvents_field), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, capabilities:=nonGenericCapabilities Or EditAndContinueCapabilities.GenericAddMethodToExistingType) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P2", FeaturesResources.auto_property), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P3", FeaturesResources.auto_property), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E1(sender As Object, e As EventArgs)", FeaturesResources.event_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E2", FeaturesResources.event_), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "WE As Object", VBFeaturesResources.WithEvents_field), + Diagnostic(RudeEditKind.InsertVirtual, "WE As Object", VBFeaturesResources.WithEvents_field), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, capabilities:=nonGenericCapabilities Or EditAndContinueCapabilities.GenericAddFieldToExistingType) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.InsertVirtual, "WE As Object", VBFeaturesResources.WithEvents_field), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, capabilities:=nonGenericCapabilities Or EditAndContinueCapabilities.GenericAddMethodToExistingType Or EditAndContinueCapabilities.GenericAddFieldToExistingType) + End Sub + + + Public Sub Type_Generic_Insert_IntoNestedType() + Dim src1 = " +Class C(Of T) + Class D + End Class +End Class +" + Dim src2 = " +Class C(Of T) + Class D + Sub F() + End Sub + + Dim X As Integer + Shared Dim Y As Integer + End Class +End Class +" + Dim edits = GetTopEdits(src1, src2) + + Dim nonGenericCapabilities = + EditAndContinueCapabilities.AddMethodToExistingType Or + EditAndContinueCapabilities.AddInstanceFieldToExistingType Or + EditAndContinueCapabilities.AddStaticFieldToExistingType + edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub M()", GetResource("method")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P1(i As Integer)", GetResource("property")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P2", "auto-property"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Property P3", "auto-property"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E1(sender As Object, e As EventArgs)", "event"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E2", "event"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Event E3", "event"), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F1", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F2", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F3 As Integer", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F4 As New Object", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F5(1, 2)", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "F6?", GetResource("field")), - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "WE As Object", GetResource("WithEvents field")), - Diagnostic(RudeEditKind.InsertVirtual, "WE As Object", GetResource("WithEvents field")), - Diagnostic(RudeEditKind.GenericTypeUpdate, "Class C(Of T)")) + { + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub F()", FeaturesResources.method), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "X As Integer", FeaturesResources.field), + Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Y As Integer", FeaturesResources.field) + }, capabilities:=nonGenericCapabilities) + + edits.VerifySemanticDiagnostics(capabilities:= + nonGenericCapabilities Or + EditAndContinueCapabilities.GenericAddMethodToExistingType Or + EditAndContinueCapabilities.GenericAddFieldToExistingType) End Sub @@ -1631,11 +1764,26 @@ End Interface DocumentResults( diagnostics:= { - Diagnostic(RudeEditKind.GenericTypeUpdate, "Sub F()"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "Sub F()"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "Sub F()") + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Sub F()", GetResource("method")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Sub F()", GetResource("method")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Sub F()", GetResource("method")) }) - }) + }, + capabilities:=EditAndContinueCapabilities.Baseline) + + EditAndContinueValidation.VerifySemantics( + {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, + { + DocumentResults(), + DocumentResults( + semanticEdits:= + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F")), + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("S.F")), + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("I.F")) + }) + }, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub @@ -3827,15 +3975,27 @@ End Class Dim srcA2 = "Partial Class C : End Class" Dim srcB2 = "Partial Class C" + vbCrLf + "Sub F(Of T)() : End Sub : End Class" + EditAndContinueValidation.VerifySemantics( + {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, + { + DocumentResults(), + DocumentResults(semanticEdits:= + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F")) + }) + }, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) + EditAndContinueValidation.VerifySemantics( {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, { DocumentResults(), DocumentResults(diagnostics:= { - Diagnostic(RudeEditKind.GenericMethodUpdate, "Sub F(Of T)()") + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Sub F(Of T)()", GetResource("method")) }) - }) + }, + capabilities:=EditAndContinueCapabilities.Baseline) End Sub @@ -3845,16 +4005,27 @@ End Class Dim srcA2 = "Partial Class C(Of T) : End Class" Dim srcB2 = "Partial Class C(Of T)" + vbCrLf + "Sub F(Of T)() : End Sub : End Class" - ' TODO better message + EditAndContinueValidation.VerifySemantics( + {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, + { + DocumentResults(), + DocumentResults(semanticEdits:= + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F")) + }) + }, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) + EditAndContinueValidation.VerifySemantics( {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, { DocumentResults(), DocumentResults(diagnostics:= { - Diagnostic(RudeEditKind.GenericMethodUpdate, "Sub F(Of T)()") + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Sub F(Of T)()", GetResource("method")) }) - }) + }, + capabilities:=EditAndContinueCapabilities.Baseline) End Sub @@ -4214,15 +4385,15 @@ End Structure EditAndContinueValidation.VerifySemantics( {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, { - DocumentResults(diagnostics:= + DocumentResults(semanticEdits:= { - Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "Sub F(Of T)()", FeaturesResources.method) + SemanticEdit(SemanticEditKind.Insert, Function(c) c.GetMembers("S.F").FirstOrDefault(Function(m) m.GetArity() = 1)) }), DocumentResults(semanticEdits:= { - SemanticEdit(SemanticEditKind.Delete, Function(c) c.GetMembers("S.F").FirstOrDefault(Function(m) m.GetTypeParameters().Length = 0), deletedSymbolContainerProvider:=Function(c) c.GetMember("S")) + SemanticEdit(SemanticEditKind.Delete, Function(c) c.GetMembers("S.F").FirstOrDefault(Function(m) m.GetArity() = 0), deletedSymbolContainerProvider:=Function(c) c.GetMember("S")) }) - }) + }, capabilities:=EditAndContinueCapabilities.AddMethodToExistingType Or EditAndContinueCapabilities.GenericAddMethodToExistingType) End Sub #End Region @@ -4675,6 +4846,88 @@ Imports System.Runtime.InteropServices capabilities:=EditAndContinueCapabilities.AddMethodToExistingType) End Sub + + Public Sub Method_Rename_GenericType() + Dim src1 = " +Class C(Of T) + Shared Sub F() + End Sub +End Class" + Dim src2 = " +Class C(Of T) + Shared Sub G() + End Sub +End Class" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "Shared Sub G()", FeaturesResources.method) + }, + capabilities:=EditAndContinueCapabilities.AddMethodToExistingType) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "Shared Sub G()", GetResource("method")) + }, + capabilities:= + EditAndContinueCapabilities.AddMethodToExistingType Or + EditAndContinueCapabilities.GenericAddMethodToExistingType) + + edits.VerifySemantics( + semanticEdits:= + { + SemanticEdit(SemanticEditKind.Delete, Function(c) c.GetMember("C.F"), deletedSymbolContainerProvider:=Function(c) c.GetMember("C")), + SemanticEdit(SemanticEditKind.Insert, Function(c) c.GetMember("C.G")) + }, + capabilities:= + EditAndContinueCapabilities.AddMethodToExistingType Or + EditAndContinueCapabilities.GenericAddMethodToExistingType Or + EditAndContinueCapabilities.GenericUpdateMethod) + End Sub + + + Public Sub Method_Rename_GenericMethod() + Dim src1 = " +Class C + Shared Sub F(Of T)() + End Sub +End Class" + Dim src2 = " +Class C + Shared Sub G(Of T)() + End Sub +End Class" + Dim edits = GetTopEdits(src1, src2) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "Shared Sub G(Of T)()", FeaturesResources.method) + }, + capabilities:= + EditAndContinueCapabilities.AddMethodToExistingType Or + EditAndContinueCapabilities.GenericUpdateMethod) + + edits.VerifySemanticDiagnostics( + { + Diagnostic(RudeEditKind.RenamingNotSupportedByRuntime, "Shared Sub G(Of T)()", FeaturesResources.method) + }, + capabilities:= + EditAndContinueCapabilities.AddMethodToExistingType Or + EditAndContinueCapabilities.GenericAddMethodToExistingType) + + edits.VerifySemantics( + semanticEdits:= + { + SemanticEdit(SemanticEditKind.Delete, Function(c) c.GetMember("C.F"), deletedSymbolContainerProvider:=Function(c) c.GetMember("C")), + SemanticEdit(SemanticEditKind.Insert, Function(c) c.GetMember("C.G")) + }, + capabilities:= + EditAndContinueCapabilities.AddMethodToExistingType Or + EditAndContinueCapabilities.GenericAddMethodToExistingType Or + EditAndContinueCapabilities.GenericUpdateMethod) + End Sub + Public Sub InterfaceMethod_Rename() Dim src1 = "Interface C : " & vbLf & "Sub Goo : End Interface" @@ -5671,7 +5924,17 @@ End Class "[Public Sub New(a As Integer) : End Sub]@14") edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "Public Sub New(a As Integer)")) + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Public Sub New(a As Integer)", GetResource("constructor")) + }, + capabilities:=EditAndContinueCapabilities.Baseline) + + edits.VerifySemantics( + semanticEdits:= + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").InstanceConstructors.Single(), preserveLocalVariables:=True) + }, + capabilities:=EditAndContinueCapabilities.Baseline Or EditAndContinueCapabilities.GenericUpdateMethod) End Sub @@ -8868,8 +9131,16 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "a As Integer = 2"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "Class C(Of T)")) + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "a As Integer = 2", GetResource("field")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, + capabilities:=EditAndContinueCapabilities.Baseline) + + edits.VerifySemantics( + ActiveStatementsDescription.Empty, + {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").InstanceConstructors.Single(), preserveLocalVariables:=True)}, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub @@ -8879,8 +9150,16 @@ End Class Dim edits = GetTopEdits(src1, src2) edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericTypeUpdate, "Property a"), - Diagnostic(RudeEditKind.GenericTypeUpdate, "Class C(Of T)")) + { + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Property a", GetResource("property")), + Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "Class C(Of T)", GetResource("constructor", "New()")) + }, + capabilities:=EditAndContinueCapabilities.Baseline) + + edits.VerifySemantics( + ActiveStatementsDescription.Empty, + {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").InstanceConstructors.Single(), preserveLocalVariables:=True)}, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub @@ -11018,7 +11297,7 @@ End Class Public Sub MethodTypeParameterInsert1() - Dim src1 = "Class C : " & vbLf & "Public Sub M()" & vbLf & "End Sub : End Class" + Dim src1 = "Class C : " & vbLf & "Public Sub M ()" & vbLf & "End Sub : End Class" Dim src2 = "Class C : " & vbLf & "Public Sub M(Of A)()" & vbLf & "End Sub : End Class" Dim edits = GetTopEdits(src1, src2) @@ -11032,23 +11311,22 @@ End Class Public Sub MethodTypeParameterInsert2() - Dim src1 = "Class C : " & vbLf & "Public Sub M(Of A)()" & vbLf & "End Sub : End Class" + Dim src1 = "Class C : " & vbLf & "Public Sub M(Of A )()" & vbLf & "End Sub : End Class" Dim src2 = "Class C : " & vbLf & "Public Sub M(Of A, B)()" & vbLf & "End Sub : End Class" Dim edits = GetTopEdits(src1, src2) edits.VerifyEdits( - "Update [(Of A)]@23 -> [(Of A, B)]@23", + "Update [(Of A )]@23 -> [(Of A, B)]@23", "Insert [B]@30") edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, " ", FeaturesResources.method), Diagnostic(RudeEditKind.Insert, "B", FeaturesResources.type_parameter)) End Sub Public Sub MethodTypeParameterDelete1() Dim src1 = "Class C : " & vbLf & "Public Sub M(Of A)() : End Sub : End Class" - Dim src2 = "Class C : " & vbLf & "Public Sub M() : End Sub : End Class" + Dim src2 = "Class C : " & vbLf & "Public Sub M () : End Sub : End Class" Dim edits = GetTopEdits(src1, src2) edits.VerifyEdits( @@ -11056,23 +11334,23 @@ End Class "Delete [A]@27") edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.Delete, "Public Sub M()", DeletedSymbolDisplay(FeaturesResources.type_parameter, "A")), - Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, " : ", FeaturesResources.method)) + {Diagnostic(RudeEditKind.Delete, "Public Sub M ()", GetResource("type parameter", "A"))}, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub Public Sub MethodTypeParameterDelete2() Dim src1 = "Class C : " & vbLf & "Public Sub M(Of A, B)()" & vbLf & "End Sub : End Class" - Dim src2 = "Class C : " & vbLf & "Public Sub M(Of B)()" & vbLf & "End Sub : End Class" + Dim src2 = "Class C : " & vbLf & "Public Sub M(Of B )()" & vbLf & "End Sub : End Class" Dim edits = GetTopEdits(src1, src2) edits.VerifyEdits( - "Update [(Of A, B)]@23 -> [(Of B)]@23", + "Update [(Of A, B)]@23 -> [(Of B )]@23", "Delete [A]@27") edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, "", FeaturesResources.method), - Diagnostic(RudeEditKind.Delete, "Public Sub M(Of B)()", DeletedSymbolDisplay(FeaturesResources.type_parameter, "A"))) + {Diagnostic(RudeEditKind.Delete, "Public Sub M(Of B )()", GetResource("type parameter", "A"))}, + capabilities:=EditAndContinueCapabilities.GenericUpdateMethod) End Sub diff --git a/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs index 7d143f36ddf5b..2fb846cb8ca02 100644 --- a/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs +++ b/src/Features/CSharpTest/SplitOrMergeIfStatements/MergeConsecutiveIfStatementsTests_ElseIf_Middle.cs @@ -22,10 +22,10 @@ void M(bool a, bool b, bool c) { if (a) System.Console.WriteLine(null); - [||]else if (b) + [||]else {|applicableSpan:if (b) System.Console.WriteLine(); else if (c) - System.Console.WriteLine(); + System.Console.WriteLine();|} } } """; @@ -45,6 +45,7 @@ void M(bool a, bool b, bool c) await TestActionCountAsync(Initial, 1); await TestInRegularAndScriptAsync(Initial, Expected); + await TestCodeRefactoringApplicableTextSpan(Initial, "applicableSpan"); } [Fact] diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs index 5cce53b0c9bd7..bdc6a5f79b974 100644 --- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs +++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs @@ -75,7 +75,7 @@ protected AbstractEditAndContinueAnalyzer(Action? testFaultInjector) } private static TraceLog Log - => EditAndContinueWorkspaceService.AnalysisLog; + => EditAndContinueService.AnalysisLog; internal abstract bool ExperimentalFeaturesEnabled(SyntaxTree tree); @@ -3267,10 +3267,9 @@ protected virtual bool IsRudeEditDueToPrimaryConstructor(ISymbol symbol, Cancell } // updating generic methods and types - if (InGenericContext(oldSymbol, out var oldIsGenericMethod)) + if (InGenericContext(oldSymbol) && !capabilities.Grant(EditAndContinueCapabilities.GenericUpdateMethod)) { - var rudeEdit = oldIsGenericMethod ? RudeEditKind.GenericMethodTriviaUpdate : RudeEditKind.GenericTypeTriviaUpdate; - diagnostics.Add(new RudeEditDiagnostic(rudeEdit, diagnosticSpan, newEditNode, new[] { GetDisplayName(newEditNode) })); + diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, diagnosticSpan, newEditNode, new[] { GetDisplayName(newEditNode) })); continue; } @@ -3707,16 +3706,13 @@ public int GetHashCode([DisallowNull] SemanticEditInfo obj) diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.UpdatingStateMachineMethodNotSupportedByRuntime, GetDiagnosticSpan(newDeclaration, EditKind.Update))); } - var newIsGenericMethod = false; - var oldInGenericLocalContext = false; - var newInGenericLocalContext = false; - if (InGenericContext(oldMember, out var oldIsGenericMethod) || - InGenericContext(newMember, out newIsGenericMethod) || - (oldInGenericLocalContext = InGenericLocalContext(oldBody, memberBodyMatch.OldRoot)) || - (newInGenericLocalContext = InGenericLocalContext(newBody, memberBodyMatch.NewRoot))) + if ((InGenericContext(oldMember) || + InGenericContext(newMember) || + InGenericLocalContext(oldBody, memberBodyMatch.OldRoot) || + InGenericLocalContext(newBody, memberBodyMatch.NewRoot)) && + !capabilities.Grant(EditAndContinueCapabilities.GenericAddFieldToExistingType)) { - var rudeEdit = oldIsGenericMethod || newIsGenericMethod || oldInGenericLocalContext || newInGenericLocalContext ? RudeEditKind.GenericMethodUpdate : RudeEditKind.GenericTypeUpdate; - diagnostics.Add(new RudeEditDiagnostic(rudeEdit, GetDiagnosticSpan(newDeclaration, EditKind.Update), newDeclaration)); + diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, GetDiagnosticSpan(newDeclaration, EditKind.Update), newDeclaration, new[] { GetDisplayName(newDeclaration) })); } } } @@ -4016,13 +4012,12 @@ public int GetHashCode([DisallowNull] SemanticEditInfo obj) } // updating within generic context - var oldIsGenericMethod = false; - var newIsGenericMethod = false; if (rudeEdit == RudeEditKind.None && oldSymbol is not INamedTypeSymbol and not ITypeParameterSymbol and not IParameterSymbol && - (InGenericContext(oldSymbol, out oldIsGenericMethod) || InGenericContext(newSymbol, out newIsGenericMethod))) + (InGenericContext(oldSymbol) || InGenericContext(newSymbol)) && + !capabilities.Grant(EditAndContinueCapabilities.GenericUpdateMethod)) { - rudeEdit = oldIsGenericMethod || newIsGenericMethod ? RudeEditKind.GenericMethodUpdate : RudeEditKind.GenericTypeUpdate; + rudeEdit = RudeEditKind.UpdatingGenericNotSupportedByRuntime; } if (rudeEdit != RudeEditKind.None) @@ -4558,7 +4553,7 @@ static bool IsSecurityAttribute(INamedTypeSymbol namedTypeSymbol) /// private bool CanRenameOrChangeSignature(ISymbol oldSymbol, ISymbol newSymbol, EditAndContinueCapabilitiesGrantor capabilities, CancellationToken cancellationToken) => CanAddNewMemberToExistingType(newSymbol, capabilities, cancellationToken) && - CanUpdateMemberBody(oldSymbol, newSymbol); + CanUpdateMemberBody(oldSymbol, newSymbol, capabilities); private bool CanAddNewMemberToExistingType(ISymbol newSymbol, EditAndContinueCapabilitiesGrantor capabilities, CancellationToken cancellationToken) { @@ -4575,19 +4570,19 @@ private bool CanAddNewMemberToExistingType(ISymbol newSymbol, EditAndContinueCap } // Inserting a member into an existing generic type, or a generic method into a type is only allowed if the runtime supports it - if (newSymbol is not INamedTypeSymbol && InGenericContext(newSymbol, out _)) + if (newSymbol is not INamedTypeSymbol && InGenericContext(newSymbol)) { - return false; + requiredCapabilities |= newSymbol is IFieldSymbol ? EditAndContinueCapabilities.GenericAddFieldToExistingType : EditAndContinueCapabilities.GenericAddMethodToExistingType; } return capabilities.Grant(requiredCapabilities); } - private static bool CanUpdateMemberBody(ISymbol oldSymbol, ISymbol newSymbol) + private static bool CanUpdateMemberBody(ISymbol oldSymbol, ISymbol newSymbol, EditAndContinueCapabilitiesGrantor capabilities) { - if (InGenericContext(oldSymbol, out _) || InGenericContext(newSymbol, out _)) + if (InGenericContext(oldSymbol) || InGenericContext(newSymbol)) { - return false; + return capabilities.Grant(EditAndContinueCapabilities.GenericUpdateMethod); } return true; @@ -5247,9 +5242,10 @@ static bool IsNotInDocument(SyntaxReference reference, SyntaxTree syntaxTree) oldStateMachineInfo, newStateMachineInfo); - if (IsGenericLocalFunction(oldLambda) || IsGenericLocalFunction(newLambda)) + if ((IsGenericLocalFunction(oldLambda) || IsGenericLocalFunction(newLambda)) && + !capabilities.Grant(EditAndContinueCapabilities.GenericUpdateMethod)) { - diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.GenericMethodUpdate, GetDiagnosticSpan(newLambda, EditKind.Update), newLambda, new[] { GetDisplayName(newLambda) })); + diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, GetDiagnosticSpan(newLambda, EditKind.Update), newLambda, new[] { GetDisplayName(newLambda) })); } } } @@ -5466,7 +5462,7 @@ select clausesByQuery.First()) var containingTypeDeclaration = TryGetContainingTypeDeclaration(newMemberBody); var isInInterfaceDeclaration = containingTypeDeclaration != null && IsInterfaceDeclaration(containingTypeDeclaration); - var isNewMemberInGenericContext = InGenericContext(newMember, out _); + var isNewMemberInGenericContext = InGenericContext(newMember); var newHasLambdaBodies = newHasLambdasOrLocalFunctions; while (newHasLambdaBodies) @@ -5526,7 +5522,7 @@ bool CanAddNewLambda(SyntaxNode newLambda, SyntaxNode newLambdaBody1, SyntaxNode if (isNewMemberInGenericContext || inGenericLocalContext) { - return false; + requiredCapabilities |= EditAndContinueCapabilities.GenericAddMethodToExistingType; } // Static lambdas are cached in static fields, unless in generic local functions. @@ -5540,6 +5536,12 @@ bool CanAddNewLambda(SyntaxNode newLambda, SyntaxNode newLambdaBody1, SyntaxNode if (isLambdaCachedInField) { requiredCapabilities |= EditAndContinueCapabilities.AddStaticFieldToExistingType; + + // If we are in a generic type or a member then the closure type is generic and we are adding a static field to a generic type. + if (isNewMemberInGenericContext) + { + requiredCapabilities |= EditAndContinueCapabilities.GenericAddFieldToExistingType; + } } // If the old verison of the method had any lambdas the nwe know a closure type exists and a new one isn't needed. @@ -6207,7 +6209,7 @@ public int GetHashCode(KeyValuePair obj) private static bool IsGlobalMain(ISymbol symbol) => symbol is IMethodSymbol { Name: WellKnownMemberNames.TopLevelStatementsEntryPointMethodName }; - private static bool InGenericContext(ISymbol symbol, out bool isGenericMethod) + private static bool InGenericContext(ISymbol symbol) { var current = symbol; @@ -6215,20 +6217,17 @@ private static bool InGenericContext(ISymbol symbol, out bool isGenericMethod) { if (current is IMethodSymbol { Arity: > 0 }) { - isGenericMethod = true; return true; } if (current is INamedTypeSymbol { Arity: > 0 }) { - isGenericMethod = false; return true; } current = current.ContainingSymbol; if (current == null) { - isGenericMethod = false; return false; } } diff --git a/src/Features/Core/Portable/EditAndContinue/CommittedSolution.cs b/src/Features/Core/Portable/EditAndContinue/CommittedSolution.cs index 05f6c55e5a433..79a28a02e3f3c 100644 --- a/src/Features/Core/Portable/EditAndContinue/CommittedSolution.cs +++ b/src/Features/Core/Portable/EditAndContinue/CommittedSolution.cs @@ -414,14 +414,14 @@ await TryGetMatchingSourceTextAsync(sourceText, sourceFilePath, currentDocument: if (debugInfoReaderProvider == null) { - EditAndContinueWorkspaceService.Log.Write("Source file of project '{0}' doesn't match output PDB: PDB '{1}' (assembly: '{2}') not found", projectName, compilationOutputs.PdbDisplayPath, compilationOutputs.AssemblyDisplayPath); + EditAndContinueService.Log.Write("Source file of project '{0}' doesn't match output PDB: PDB '{1}' (assembly: '{2}') not found", projectName, compilationOutputs.PdbDisplayPath, compilationOutputs.AssemblyDisplayPath); } return debugInfoReaderProvider; } catch (Exception e) { - EditAndContinueWorkspaceService.Log.Write("Source file of project '{0}' doesn't match output PDB: error opening PDB '{1}' (assembly: '{2}'): {3}", projectName, compilationOutputs.PdbDisplayPath, compilationOutputs.AssemblyDisplayPath, e.Message); + EditAndContinueService.Log.Write("Source file of project '{0}' doesn't match output PDB: error opening PDB '{1}' (assembly: '{2}'): {3}", projectName, compilationOutputs.PdbDisplayPath, compilationOutputs.AssemblyDisplayPath, e.Message); return null; } } @@ -454,14 +454,14 @@ private static bool IsMatchingSourceText(SourceText sourceText, ImmutableArray UpdateParameters = 1 << 6, + + /// + /// Adding a static or instance method, property or event to an existing type (without backing fields), such that the method and/or the type are generic. + /// + GenericAddMethodToExistingType = 1 << 7, + + /// + /// Updating an existing static or instance method, property or event (without backing fields) that is generic and/or contained in a generic type. + /// + GenericUpdateMethod = 1 << 8, + + /// + /// Adding a static or instance field to an existing generic type. + /// + GenericAddFieldToExistingType = 1 << 9, } internal static class EditAndContinueCapabilitiesParser @@ -69,6 +84,9 @@ public static EditAndContinueCapabilities Parse(ImmutableArray capabilit nameof(EditAndContinueCapabilities.NewTypeDefinition) => EditAndContinueCapabilities.NewTypeDefinition, nameof(EditAndContinueCapabilities.ChangeCustomAttributes) => EditAndContinueCapabilities.ChangeCustomAttributes, nameof(EditAndContinueCapabilities.UpdateParameters) => EditAndContinueCapabilities.UpdateParameters, + nameof(EditAndContinueCapabilities.GenericAddMethodToExistingType) => EditAndContinueCapabilities.GenericAddMethodToExistingType, + nameof(EditAndContinueCapabilities.GenericUpdateMethod) => EditAndContinueCapabilities.GenericUpdateMethod, + nameof(EditAndContinueCapabilities.GenericAddFieldToExistingType) => EditAndContinueCapabilities.GenericAddFieldToExistingType, // To make it eaiser for runtimes to specify more broad capabilities "AddDefinitionToExistingType" => EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType, diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs index eb7fb59bc9dcd..9441f658f5ed8 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs @@ -93,14 +93,10 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddRudeEdit(RudeEditKind.InsertOperator, nameof(FeaturesResources.Adding_a_user_defined_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.InsertIntoStruct, nameof(FeaturesResources.Adding_0_into_a_1_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.InsertIntoClassWithLayout, nameof(FeaturesResources.Adding_0_into_a_class_with_explicit_or_sequential_layout_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.InsertGenericMethod, nameof(FeaturesResources.Adding_a_generic_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.Move, nameof(FeaturesResources.Moving_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.Delete, nameof(FeaturesResources.Deleting_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.GenericMethodUpdate, nameof(FeaturesResources.Modifying_a_generic_method_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.GenericMethodTriviaUpdate, nameof(FeaturesResources.Modifying_whitespace_or_comments_in_a_generic_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.GenericTypeUpdate, nameof(FeaturesResources.Modifying_a_method_inside_the_context_of_a_generic_type_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.GenericTypeTriviaUpdate, nameof(FeaturesResources.Modifying_whitespace_or_comments_in_0_inside_the_context_of_a_generic_type_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.GenericTypeInitializerUpdate, nameof(FeaturesResources.Modifying_the_initializer_of_0_in_a_generic_type_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.InsertConstructorToTypeWithInitializersWithLambdas, nameof(FeaturesResources.Adding_a_constructor_to_a_type_with_a_field_or_property_initializer_that_contains_an_anonymous_function_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.RenamingCapturedVariable, nameof(FeaturesResources.Renaming_a_captured_variable_from_0_to_1_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.StackAllocUpdate, nameof(FeaturesResources.Modifying_0_which_contains_the_stackalloc_operator_requires_restarting_the_application)); @@ -137,7 +133,6 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddRudeEdit(RudeEditKind.MemberBodyInternalError, nameof(FeaturesResources.Modifying_body_of_0_requires_restarting_the_application_due_to_internal_error_1)); AddRudeEdit(RudeEditKind.MemberBodyTooBig, nameof(FeaturesResources.Modifying_body_of_0_requires_restarting_the_application_because_the_body_has_too_many_statements)); AddRudeEdit(RudeEditKind.SourceFileTooBig, nameof(FeaturesResources.Modifying_source_file_0_requires_restarting_the_application_because_the_file_is_too_big)); - AddRudeEdit(RudeEditKind.InsertIntoGenericType, nameof(FeaturesResources.Adding_0_into_a_generic_type_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ImplementRecordParameterAsReadOnly, nameof(FeaturesResources.Implementing_a_record_positional_parameter_0_as_read_only_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ImplementRecordParameterWithSet, nameof(FeaturesResources.Implementing_a_record_positional_parameter_0_with_a_set_accessor_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ExplicitRecordMethodParameterNamesMustMatch, nameof(FeaturesResources.Explicitly_implemented_methods_of_records_must_have_parameter_names_that_match_the_compiler_generated_equivalent_0)); @@ -157,6 +152,7 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddRudeEdit(RudeEditKind.ChangingTypeNotSupportedByRuntime, nameof(FeaturesResources.Changing_the_type_of_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.DeleteNotSupportedByRuntime, nameof(FeaturesResources.Deleting_0_requires_restarting_the_application_because_is_not_supported_by_the_runtime)); AddRudeEdit(RudeEditKind.UpdatingStateMachineMethodNotSupportedByRuntime, nameof(FeaturesResources.Updating_async_or_iterator_requires_restarting_the_application_because_is_not_supported_by_the_runtime)); + AddRudeEdit(RudeEditKind.UpdatingGenericNotSupportedByRuntime, nameof(FeaturesResources.Updating_0_within_generic_type_or_method_requires_restarting_the_application_because_is_not_supported_by_the_runtime)); // VB specific AddRudeEdit(RudeEditKind.HandlesClauseUpdate, nameof(FeaturesResources.Updating_the_Handles_clause_of_0_requires_restarting_the_application)); diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueWorkspaceService.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueService.cs similarity index 94% rename from src/Features/Core/Portable/EditAndContinue/EditAndContinueWorkspaceService.cs rename to src/Features/Core/Portable/EditAndContinue/EditAndContinueService.cs index e6803da1d3971..3dbdce1f4dbee 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueWorkspaceService.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueService.cs @@ -23,9 +23,20 @@ namespace Microsoft.CodeAnalysis.EditAndContinue /// /// Implements core of Edit and Continue orchestration: management of edit sessions and connecting EnC related services. /// - [ExportWorkspaceService(typeof(IEditAndContinueWorkspaceService)), Shared] - internal sealed class EditAndContinueWorkspaceService : IEditAndContinueWorkspaceService + [Export(typeof(IEditAndContinueService)), Shared] + internal sealed class EditAndContinueService : IEditAndContinueService { + [ExportWorkspaceService(typeof(IEditAndContinueWorkspaceService)), Shared] + internal sealed class WorkspaceService : IEditAndContinueWorkspaceService + { + public IEditAndContinueService Service { get; } + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public WorkspaceService(IEditAndContinueService service) + => Service = service; + } + internal static readonly TraceLog Log; internal static readonly TraceLog AnalysisLog; @@ -39,12 +50,12 @@ internal sealed class EditAndContinueWorkspaceService : IEditAndContinueWorkspac [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public EditAndContinueWorkspaceService() + public EditAndContinueService() { _compilationOutputsProvider = GetCompilationOutputs; } - static EditAndContinueWorkspaceService() + static EditAndContinueService() { Log = new(2048, "EnC", "Trace.log"); AnalysisLog = new(1024, "EnC", "Analysis.log"); @@ -278,9 +289,9 @@ internal TestAccessor GetTestAccessor() internal readonly struct TestAccessor { - private readonly EditAndContinueWorkspaceService _service; + private readonly EditAndContinueService _service; - public TestAccessor(EditAndContinueWorkspaceService service) + public TestAccessor(EditAndContinueService service) { _service = service; } diff --git a/src/Features/Core/Portable/EditAndContinue/EditSession.cs b/src/Features/Core/Portable/EditAndContinue/EditSession.cs index 8f668b75b346a..7bcf0c5ce31c6 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditSession.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditSession.cs @@ -796,7 +796,7 @@ public async ValueTask EmitSolutionUpdateAsync(Solution solution { try { - var log = EditAndContinueWorkspaceService.Log; + var log = EditAndContinueService.Log; log.Write("EmitSolutionUpdate {0}.{1}: '{2}'", updateId.SessionId.Ordinal, updateId.Ordinal, solution.FilePath); diff --git a/src/Features/Core/Portable/EditAndContinue/IEditAndContinueWorkspaceService.cs b/src/Features/Core/Portable/EditAndContinue/IEditAndContinueService.cs similarity index 96% rename from src/Features/Core/Portable/EditAndContinue/IEditAndContinueWorkspaceService.cs rename to src/Features/Core/Portable/EditAndContinue/IEditAndContinueService.cs index 5f2d9d2e892f8..1650f56fc9c79 100644 --- a/src/Features/Core/Portable/EditAndContinue/IEditAndContinueWorkspaceService.cs +++ b/src/Features/Core/Portable/EditAndContinue/IEditAndContinueService.cs @@ -12,6 +12,11 @@ namespace Microsoft.CodeAnalysis.EditAndContinue { internal interface IEditAndContinueWorkspaceService : IWorkspaceService + { + IEditAndContinueService Service { get; } + } + + internal interface IEditAndContinueService { ValueTask> GetDocumentDiagnosticsAsync(Document document, ActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken); ValueTask EmitSolutionUpdateAsync(DebuggingSessionId sessionId, Solution solution, ActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken); diff --git a/src/Features/Core/Portable/EditAndContinue/Remote/RemoteDebuggingSessionProxy.cs b/src/Features/Core/Portable/EditAndContinue/Remote/RemoteDebuggingSessionProxy.cs index aa9b181c18b44..b9368b758d783 100644 --- a/src/Features/Core/Portable/EditAndContinue/Remote/RemoteDebuggingSessionProxy.cs +++ b/src/Features/Core/Portable/EditAndContinue/Remote/RemoteDebuggingSessionProxy.cs @@ -35,8 +35,8 @@ public void Dispose() _connection?.Dispose(); } - private IEditAndContinueWorkspaceService GetLocalService() - => _workspace.Services.GetRequiredService(); + private IEditAndContinueService GetLocalService() + => _workspace.Services.GetRequiredService().Service; public async ValueTask BreakStateOrCapabilitiesChangedAsync(IDiagnosticAnalyzerService diagnosticService, EditAndContinueDiagnosticUpdateSource diagnosticUpdateSource, bool? inBreakState, CancellationToken cancellationToken) { diff --git a/src/Features/Core/Portable/EditAndContinue/Remote/RemoteEditAndContinueServiceProxy.cs b/src/Features/Core/Portable/EditAndContinue/Remote/RemoteEditAndContinueServiceProxy.cs index 6fdff9e149518..bc1644a06e065 100644 --- a/src/Features/Core/Portable/EditAndContinue/Remote/RemoteEditAndContinueServiceProxy.cs +++ b/src/Features/Core/Portable/EditAndContinue/Remote/RemoteEditAndContinueServiceProxy.cs @@ -132,8 +132,8 @@ public RemoteEditAndContinueServiceProxy(Workspace workspace) Workspace = workspace; } - private IEditAndContinueWorkspaceService GetLocalService() - => Workspace.Services.GetRequiredService(); + private IEditAndContinueService GetLocalService() + => Workspace.Services.GetRequiredService().Service; public async ValueTask StartDebuggingSessionAsync( Solution solution, diff --git a/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs b/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs index 3a3dad089de9c..56b6fad495d43 100644 --- a/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs +++ b/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs @@ -41,7 +41,7 @@ internal enum RudeEditKind : ushort InsertExtern = 25, InsertOperator = 26, // InsertNonPublicConstructor = 27, - InsertGenericMethod = 28, + // InsertGenericMethod = 28, InsertDllImport = 29, InsertIntoStruct = 30, InsertIntoClassWithLayout = 31, @@ -50,10 +50,10 @@ internal enum RudeEditKind : ushort // MethodBodyAdd = 34, // MethodBodyDelete = 35, GenericMethodUpdate = 36, - GenericMethodTriviaUpdate = 37, + // GenericMethodTriviaUpdate = 37, GenericTypeUpdate = 38, - GenericTypeTriviaUpdate = 39, - GenericTypeInitializerUpdate = 40, + // GenericTypeTriviaUpdate = 39, + // GenericTypeInitializerUpdate = 40, // PartialTypeInitializerUpdate = 41, // AsyncMethodUpdate = 42, // AsyncMethodTriviaUpdate = 43, @@ -116,7 +116,7 @@ internal enum RudeEditKind : ushort MemberBodyInternalError = 88, SourceFileTooBig = 89, MemberBodyTooBig = 90, - InsertIntoGenericType = 91, + // InsertIntoGenericType = 91, ImplementRecordParameterAsReadOnly = 92, ImplementRecordParameterWithSet = 93, @@ -139,5 +139,6 @@ internal enum RudeEditKind : ushort ChangingTypeNotSupportedByRuntime = 110, DeleteNotSupportedByRuntime = 111, UpdatingStateMachineMethodNotSupportedByRuntime = 112, + UpdatingGenericNotSupportedByRuntime = 113, } } diff --git a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingHotReloadService.cs b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingHotReloadService.cs index 70d6028a96f96..0dcb4958d23db 100644 --- a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingHotReloadService.cs +++ b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingHotReloadService.cs @@ -70,11 +70,11 @@ public ValueTask PrepareModuleForUpdateAsync(Guid module, CancellationToken canc private static readonly ImmutableArray EmptyUpdate = ImmutableArray.Create(); private static readonly ImmutableArray EmptyDiagnostic = ImmutableArray.Create(); - private readonly IEditAndContinueWorkspaceService _encService; + private readonly IEditAndContinueService _encService; private DebuggingSessionId _sessionId; public UnitTestingHotReloadService(HostWorkspaceServices services) - => _encService = services.GetRequiredService(); + => _encService = services.GetRequiredService().Service; /// /// Starts the watcher. diff --git a/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs b/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs index e35e2a5d18117..70cb8703a0402 100644 --- a/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs +++ b/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs @@ -59,12 +59,12 @@ internal Update(Guid moduleId, ImmutableArray ilDelta, ImmutableArray ValueTaskFactory.FromResult(ImmutableArray.Empty); - private readonly IEditAndContinueWorkspaceService _encService; + private readonly IEditAndContinueService _encService; private DebuggingSessionId _sessionId; private readonly ImmutableArray _capabilities; public WatchHotReloadService(HostWorkspaceServices services, ImmutableArray capabilities) - => (_encService, _capabilities) = (services.GetRequiredService(), capabilities); + => (_encService, _capabilities) = (services.GetRequiredService().Service, capabilities); /// /// Starts the watcher. diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index e2918a08df2d3..1137eac7109a1 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -414,9 +414,6 @@ Adding {0} into an interface requires restarting the application. - - Adding {0} into a generic type requires restarting the application. - Adding {0} into an interface method requires restarting the application. @@ -496,9 +493,6 @@ Adding a user defined {0} requires restarting the application. - - Adding a generic {0} requires restarting the application. - Adding {0} around an active statement requires restarting the application. @@ -524,18 +518,9 @@ Modifying a generic method requires restarting the application. - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Modifying a method inside the context of a generic type requires restarting the application. - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - - - Modifying the initializer of {0} in a generic type requires restarting the application. - Adding a constructor to a type with a field or property initializer that contains an anonymous function requires restarting the application. @@ -3121,6 +3106,9 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Deleting {0} requires restarting the application because is not supported by the runtime. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating async or iterator requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs index a52d823d26db6..c97b4d3352ead 100644 --- a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs @@ -113,9 +113,13 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte GetExistingMemberInfo( containingType, out var hasEquals, out var hasGetHashCode); + var globalOptions = document.Project.Solution.Services.GetService(); + if (globalOptions == null) + return; + var actions = await CreateActionsAsync( document, typeDeclaration, containingType, viableMembers, fallbackOptions, - hasEquals, hasGetHashCode, withDialog: true, cancellationToken).ConfigureAwait(false); + hasEquals, hasGetHashCode, withDialog: true, globalOptions, cancellationToken).ConfigureAwait(false); context.RegisterRefactorings(actions, textSpan); } @@ -190,7 +194,7 @@ private static void GetExistingMemberInfo(INamedTypeSymbol containingType, out b return await CreateActionsAsync( document, typeDeclaration, info.ContainingType, info.SelectedMembers, fallbackOptions, - hasEquals, hasGetHashCode, withDialog: false, cancellationToken).ConfigureAwait(false); + hasEquals, hasGetHashCode, withDialog: false, globalOptions: null, cancellationToken).ConfigureAwait(false); } } @@ -201,7 +205,7 @@ private static void GetExistingMemberInfo(INamedTypeSymbol containingType, out b private async Task> CreateActionsAsync( Document document, SyntaxNode typeDeclaration, INamedTypeSymbol containingType, ImmutableArray selectedMembers, CleanCodeGenerationOptionsProvider fallbackOptions, - bool hasEquals, bool hasGetHashCode, bool withDialog, CancellationToken cancellationToken) + bool hasEquals, bool hasGetHashCode, bool withDialog, ILegacyGlobalOptionsWorkspaceService? globalOptions, CancellationToken cancellationToken) { using var _ = ArrayBuilder>.GetInstance(out var tasks); @@ -215,42 +219,50 @@ private static void GetExistingMemberInfo(INamedTypeSymbol containingType, out b // the user would need to bother just generating that member without also // generating 'Equals' as well. tasks.Add(CreateCodeActionAsync( - document, typeDeclaration, containingType, selectedMembers, fallbackOptions, + document, typeDeclaration, containingType, selectedMembers, fallbackOptions, globalOptions, generateEquals: true, generateGetHashCode: false, withDialog, cancellationToken)); tasks.Add(CreateCodeActionAsync( - document, typeDeclaration, containingType, selectedMembers, fallbackOptions, + document, typeDeclaration, containingType, selectedMembers, fallbackOptions, globalOptions, generateEquals: true, generateGetHashCode: true, withDialog, cancellationToken)); } else if (!hasEquals) { tasks.Add(CreateCodeActionAsync( - document, typeDeclaration, containingType, selectedMembers, fallbackOptions, + document, typeDeclaration, containingType, selectedMembers, fallbackOptions, globalOptions, generateEquals: true, generateGetHashCode: false, withDialog, cancellationToken)); } else if (!hasGetHashCode) { tasks.Add(CreateCodeActionAsync( - document, typeDeclaration, containingType, selectedMembers, fallbackOptions, + document, typeDeclaration, containingType, selectedMembers, fallbackOptions, globalOptions, generateEquals: false, generateGetHashCode: true, withDialog, cancellationToken)); } var codeActions = await Task.WhenAll(tasks).ConfigureAwait(false); return codeActions.ToImmutableArray(); + } private Task CreateCodeActionAsync( Document document, SyntaxNode typeDeclaration, INamedTypeSymbol containingType, ImmutableArray members, - CleanCodeGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, ILegacyGlobalOptionsWorkspaceService? globalOptions, bool generateEquals, bool generateGetHashCode, bool withDialog, CancellationToken cancellationToken) { - return withDialog - ? CreateCodeActionWithDialogAsync(document, typeDeclaration, containingType, members, fallbackOptions, generateEquals, generateGetHashCode, cancellationToken) - : CreateCodeActionWithoutDialogAsync(document, typeDeclaration, containingType, members, fallbackOptions, generateEquals, generateGetHashCode, cancellationToken); + if (withDialog) + { + // We can't create dialog code action if globalOptions is null + Contract.ThrowIfNull(globalOptions); + return CreateCodeActionWithDialogAsync(document, typeDeclaration, containingType, members, fallbackOptions, globalOptions, generateEquals, generateGetHashCode, cancellationToken); + } + else + { + return CreateCodeActionWithoutDialogAsync(document, typeDeclaration, containingType, members, fallbackOptions, generateEquals, generateGetHashCode, cancellationToken); + } } private async Task CreateCodeActionWithDialogAsync( Document document, SyntaxNode typeDeclaration, INamedTypeSymbol containingType, ImmutableArray members, - CleanCodeGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, ILegacyGlobalOptionsWorkspaceService globalOptions, bool generateEquals, bool generateGetHashCode, CancellationToken cancellationToken) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); @@ -259,7 +271,6 @@ private static void GetExistingMemberInfo(INamedTypeSymbol containingType, out b if (CanImplementIEquatable(semanticModel, containingType, out var equatableTypeOpt)) { - var globalOptions = document.Project.Solution.Services.GetRequiredService(); var value = globalOptions.GetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(document.Project.Language); var displayName = equatableTypeOpt.ToDisplayString(new SymbolDisplayFormat( @@ -274,7 +285,6 @@ private static void GetExistingMemberInfo(INamedTypeSymbol containingType, out b if (!HasOperators(containingType)) { - var globalOptions = document.Project.Solution.Services.GetRequiredService(); var value = globalOptions.GetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(document.Project.Language); pickMembersOptions.Add(new PickMembersOption( diff --git a/src/Features/Core/Portable/SplitOrMergeIfStatements/AbstractMergeIfStatementsCodeRefactoringProvider.cs b/src/Features/Core/Portable/SplitOrMergeIfStatements/AbstractMergeIfStatementsCodeRefactoringProvider.cs index 2388864694e8e..84aac4e38bdaf 100644 --- a/src/Features/Core/Portable/SplitOrMergeIfStatements/AbstractMergeIfStatementsCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/SplitOrMergeIfStatements/AbstractMergeIfStatementsCodeRefactoringProvider.cs @@ -57,7 +57,7 @@ void RegisterRefactoring(MergeDirection direction, TextSpan upperIfOrElseIfSpan, c => RefactorAsync(document, upperIfOrElseIfSpan, lowerIfOrElseIfSpan, c), direction, syntaxFacts.GetText(syntaxKinds.IfKeyword)), - new TextSpan(upperIfOrElseIfSpan.Start, lowerIfOrElseIfSpan.End)); + TextSpan.FromBounds(upperIfOrElseIfSpan.Start, lowerIfOrElseIfSpan.End)); } } } diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 1c5b9a0ff15ae..618b03f18a1dc 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -100,11 +100,6 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Přidání {0} do třídy s explicitním nebo sekvenčním rozložením vyžaduje restartování aplikace. - - Adding {0} into a generic type requires restarting the application. - Přidání {0} do obecného typu vyžaduje restartování aplikace. - - Adding {0} into an interface method requires restarting the application. Přidání {0} do metody rozhraní vyžaduje restartování aplikace. @@ -140,11 +135,6 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Přidání konstruktoru k typu s inicializátorem pole nebo vlastnosti, který obsahuje anonymní funkci, vyžaduje restartování aplikace. - - Adding a generic {0} requires restarting the application. - Přidání obecného {0} vyžaduje restartování aplikace. - - Adding a method with an explicit interface specifier requires restarting the application. Přidání metody s explicitním specifikátorem rozhraní vyžaduje restartování aplikace. @@ -1200,21 +1190,6 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Úprava zdroje s povolenými experimentálními jazykovými funkcemi vyžaduje restartování aplikace. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Úprava inicializátoru {0} v obecném typu vyžaduje restartování aplikace. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Úprava prázdných znaků nebo komentářů v {0} uvnitř kontextu obecného typu vyžaduje restartování aplikace. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Úprava prázdných znaků nebo komentářů v obecném {0} vyžaduje restartování aplikace. - - Move contents to namespace... Přesunout obsah do oboru názvů... @@ -2830,6 +2805,11 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Aktualizace {0} vyžaduje restartování aplikace. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Aktualizace {0} kolem aktivního příkazu vyžaduje restartování aplikace. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index c3eda6b98a89a..ccf30680f7fb9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -100,11 +100,6 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Das Hinzufügen von {0} zu einer Klasse mit explizitem oder sequenziellem Layout erfordert einen Neustart der Anwendung. - - Adding {0} into a generic type requires restarting the application. - Das Hinzufügen von {0} zu einem generischen Typ erfordert einen Neustart der Anwendung. - - Adding {0} into an interface method requires restarting the application. Das Hinzufügen von {0} zu einer Schnittstellenmethode erfordert einen Neustart der Anwendung. @@ -140,11 +135,6 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Das Hinzufügen eines Konstruktors zu einem Typ mit einem Feld- oder Eigenschafteninitialisierer, der eine anonyme Funktion enthält, erfordert einen Neustart der Anwendung. - - Adding a generic {0} requires restarting the application. - Das Hinzufügen einer generischen {0}erfordert einen Neustart der Anwendung. - - Adding a method with an explicit interface specifier requires restarting the application. Das Hinzufügen einer Methode mit einem expliziten Schnittstellenbezeichner erfordert einen Neustart der Anwendung. @@ -1200,21 +1190,6 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Das Ändern der Quelle mit aktivierten experimentellen Sprachfeatures erfordert einen Neustart der Anwendung. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Das Aktualisieren des Initialisierers von {0} in einen generischen Typ erfordert einen Neustart der Anwendung. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Das Ändern von Leerzeichen oder Kommentaren in {0} im Kontext eines generischen Typs erfordert einen Neustart der Anwendung. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Das Ändern von Leerzeichen oder Kommentaren in einer generischen {0} erfordert einen Neustart der Anwendung. - - Move contents to namespace... Inhalt in Namespace verschieben... @@ -2830,6 +2805,11 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg Das Aktualisieren von „{0}“ erfordert einen Neustart der Anwendung. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Das Aktualisieren einer {0} um eine aktive Anweisung erfordert einen Neustart der Anwendung. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index fe0531cf988d4..b1cf85449f9fa 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -100,11 +100,6 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Para agregar {0} en una clase con un diseño secuencial o explícito es necesario reiniciar la aplicación. - - Adding {0} into a generic type requires restarting the application. - Para agregar {0} a un tipo genérico, es necesario reiniciar la aplicación. - - Adding {0} into an interface method requires restarting the application. Para agregar {0} en un método de interfaz es necesario reiniciar la aplicación. @@ -140,11 +135,6 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Para agregar un constructor a un tipo con un inicializador de campo o propiedad que contiene una función anónima, es necesario reiniciar la aplicación. - - Adding a generic {0} requires restarting the application. - Para agregar un {0} genérico, es necesario reiniciar la aplicación. - - Adding a method with an explicit interface specifier requires restarting the application. Para agregar un método con un especificador de interfaz explícito, es necesario reiniciar la aplicación. @@ -1200,21 +1190,6 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Para modificar el origen con las características de lenguaje experimental habilitadas se requiere reiniciar la aplicación. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Para modificar el inicializador de {0} en un tipo genérico se requiere reiniciar la aplicación. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Para modificar espacios en blanco o comentarios en {0} dentro del contexto de un tipo genérico se requiere reiniciar la aplicación. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Para modificar espacios en blanco o comentarios en un {0}genérico es necesario reiniciar la aplicación. - - Move contents to namespace... Mover contenido al espacio de nombres... @@ -2830,6 +2805,11 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us Para actualizar "{0}" es necesario reiniciar la aplicación. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Para actualizar un {0} alrededor de una instrucción de acción, es necesario reiniciar la aplicación. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index e51b782ed02bd..391fb91300d67 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -100,11 +100,6 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai L’ajout de {0} dans une classe avec une disposition explicite ou séquentielle requiert le redémarrage de l’application. - - Adding {0} into a generic type requires restarting the application. - L’ajout de {0} dans un type générique requiert le redémarrage de l’application. - - Adding {0} into an interface method requires restarting the application. L’ajout de {0} dans une méthode d’interface requiert le redémarrage de l’application. @@ -140,11 +135,6 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai L'ajout d'un constructeur à un type avec un initialiseur de champ ou de propriété contenant une fonction anonyme requiert le redémarrage de l’application. - - Adding a generic {0} requires restarting the application. - L’ajout d’un {0} générique requiert le redémarrage de l’application. - - Adding a method with an explicit interface specifier requires restarting the application. L’ajout d’une méthode avec un spécificateur d’interface explicite requiert le redémarrage de l’application. @@ -1200,21 +1190,6 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai La modification de la source avec les fonctionnalités de langage expérimentales activées requiert le redémarrage de l’application. - - Modifying the initializer of {0} in a generic type requires restarting the application. - La modification de l’initialiseur de {0} dans un type générique requiert le redémarrage de l’application. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - La modification d’espaces blancs ou de commentaires dans {0} dans le contexte d’un type générique requiert le redémarrage de l’application. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - La modification des espaces blancs ou des commentaires dans une {0} générique requiert le redémarrage de l’application. - - Move contents to namespace... Déplacer le contenu vers un espace de noms... @@ -2830,6 +2805,11 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée La mise à jour de « {0} » requiert le redémarrage de l’application. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. La mise à jour d’un {0} autour d’une instruction active requiert le redémarrage de l’application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index afd02ee9ab330..77092efad4ec7 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -100,11 +100,6 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Se si aggiunge {0} in una classe con layout esplicito o sequenziale, è necessario riavviare l'applicazione. - - Adding {0} into a generic type requires restarting the application. - Se si aggiunge {0} in un tipo generico, è necessario riavviare l'applicazione. - - Adding {0} into an interface method requires restarting the application. Se si aggiunge {0} in un metodo di interfaccia, è necessario riavviare l'applicazione. @@ -140,11 +135,6 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Se aggiunge un costruttore a un tipo con un inizializzatore di campo o proprietà che contiene una funzione anonima, è necessario riavviare l'applicazione. - - Adding a generic {0} requires restarting the application. - Se si aggiunge un elemento {0} generico, è necessario riavviare l'applicazione. - - Adding a method with an explicit interface specifier requires restarting the application. Se si aggiunge un metodo con un identificatore di interfaccia esplicito, è necessario riavviare l'applicazione. @@ -1200,21 +1190,6 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Se si modifica l'origine con le funzionalità del linguaggio sperimentali abilitate, è necessario riavviare l'applicazione. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Se si modifica l'inizializzatore di {0} in un tipo generico, è necessario riavviare l'applicazione. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Se si modificano spazi vuoti o commenti in {0} all'interno del contesto di un tipo generico, è necessario riavviare l'applicazione. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Se si modificano spazi vuoti o commenti in un elemento {0} generico, è necessario riavviare l'applicazione. - - Move contents to namespace... Sposta contenuto nello spazio dei nomi... @@ -2830,6 +2805,11 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' Se si elimina '{0}', è necessario riavviare l'applicazione. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Se si aggiorna un elemento {0} all'inizio di un'istruzione attiva, è necessario riavviare l'applicazione. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index f72ce75eee8b2..69f149b7c7d76 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -100,11 +100,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 明示的またはシーケンシャルなレイアウトのクラスに {0} を追加するには、アプリケーションを再起動する必要があります。 - - Adding {0} into a generic type requires restarting the application. - ジェネリック型に {0} を追加するには、アプリケーションを再起動する必要があります。 - - Adding {0} into an interface method requires restarting the application. インターフェイス メソッドに {0} を追加するには、アプリケーションを再起動する必要があります。 @@ -140,11 +135,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 匿名関数を含むフィールドまたはプロパティの初期化子を持つ型にコンストラクターを追加するには、アプリケーションを再起動する必要があります。 - - Adding a generic {0} requires restarting the application. - 汎用 {0} を追加するには、アプリケーションを再起動する必要があります。 - - Adding a method with an explicit interface specifier requires restarting the application. 明示的なインターフェイス指定子を含むメソッドを追加するには、アプリケーションを再起動する必要があります。 @@ -1200,21 +1190,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 試験的な言語機能を有効にしてソースを変更するには、アプリケーションを再起動する必要があります。 - - Modifying the initializer of {0} in a generic type requires restarting the application. - ジェネリック型の {0} の初期化子を変更するには、アプリケーションを再起動する必要があります。 - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - ジェネリック型のコンテキスト内で {0} の空白またはコメントを変更するには、アプリケーションを再起動する必要があります。 - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - ジェネリックの {0} 内の空白またはコメントを変更するには、アプリケーションを再起動する必要があります。 - - Move contents to namespace... 名前空間へのコンテンツの移動... @@ -2830,6 +2805,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of '{0}' を更新するには、アプリケーションを再起動する必要があります。 + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. アクティブ ステートメントの前後の {0} を更新するには、アプリケーションを再起動する必要があります。 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index acec2103159be..2775ed8c368e9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -100,11 +100,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 명시적 또는 순차 레이아웃이 있는 클래스에 {0}을(를) 추가하려면 응용 프로그램을 다시 시작해야 합니다. - - Adding {0} into a generic type requires restarting the application. - 제네릭 형식에 {0}을(를) 추가하려면 애플리케이션을 다시 시작해야 합니다. - - Adding {0} into an interface method requires restarting the application. 인터페이스 메소드에 {0}을(를) 추가하려면 응용 프로그램을 다시 시작해야 합니다. @@ -140,11 +135,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 익명 함수가 포함된 필드 또는 속성 이니셜라이저가 있는 형식에 생성자를 추가하려면 응용 프로그램을 다시 시작해야 합니다. - - Adding a generic {0} requires restarting the application. - 제네릭 {0}을(를) 추가하려면 애플리케이션을 다시 시작해야 합니다. - - Adding a method with an explicit interface specifier requires restarting the application. 명시적 인터페이스 지정자를 사용하여 메서드를 추가하려면 애플리케이션을 다시 시작해야 합니다. @@ -1200,21 +1190,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 실험 언어 기능이 활성화된 원본를 수정하려면 응용 프로그램을 다시 시작해야 합니다. - - Modifying the initializer of {0} in a generic type requires restarting the application. - 제네릭 형식의 {0}의 이니셜라이저를 수정하려면 애플리케이션을 다시 시작해야 합니다. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - 제네릭 형식의 컨텍스트 내에서 {0}의 공백 또는 주석을 수정하려면 애플리케이션을 다시 시작해야 합니다. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - 제네릭 {0}에서 공백 또는 주석을 수정하려면 애플리케이션을 다시 시작해야 합니다. - - Move contents to namespace... 네임스페이스로 콘텐츠 이동... @@ -2830,6 +2805,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of '{0}'을(를) 업데이트하려면 애플리케이션을 다시 시작해야 합니다. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. 활성 문 주변의 {0}을(를) 업데이트하려면 응용 프로그램을 다시 시작해야 합니다. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 5eae28780fe1e..a0cc6e1a217f4 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -100,11 +100,6 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Dodawanie elementu {0} do klasy za pomocą jawnego lub sekwencyjnego układu wymaga ponownego uruchomienia aplikacji. - - Adding {0} into a generic type requires restarting the application. - Dodanie elementu {0} do typu ogólnego wymaga ponownego uruchomienia aplikacji. - - Adding {0} into an interface method requires restarting the application. Dodanie elementu {0} do metody interfejsu wymaga ponownego uruchomienia aplikacji. @@ -140,11 +135,6 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Dodanie konstruktora do typu z inicjatorem pola lub właściwości zawierającego funkcję anonimową wymaga ponownego uruchomienia aplikacji. - - Adding a generic {0} requires restarting the application. - Dodanie ogólnego elementu {0} wymaga ponownego uruchomienia aplikacji. - - Adding a method with an explicit interface specifier requires restarting the application. Dodanie metody z jawnym specyfikatorem interfejsu wymaga ponownego uruchomienia aplikacji. @@ -1200,21 +1190,6 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Modyfikowanie źródła z włączonymi funkcjami eksperymentalnymi języka wymaga ponownego uruchomienia aplikacji. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Modyfikacja inicjatora elementu {0} w typie ogólnym wymaga ponownego uruchomienia aplikacji. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Modyfikacja odstępów lub komentarzy w elemencie {0} w kontekście typu ogólnego wymaga ponownego uruchomienia aplikacji. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Modyfikacja odstępów lub komentarzy w ogólnym elemencie {0} wymaga ponownego uruchomienia aplikacji. - - Move contents to namespace... Przenieś zawartość do przestrzeni nazw... @@ -2830,6 +2805,11 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Aktualizacja elementu „{0}” wymaga ponownego uruchomienia aplikacji. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Aktualizowanie elementu {0} wokół aktywnej instrukcji wymaga ponownego uruchomienia aplikacji. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index feae5d5bafa57..d4afac1c24cd9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -100,11 +100,6 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Adicionar {0} a uma classe com layout explícito ou sequencial requer a reinicialização do aplicativo. - - Adding {0} into a generic type requires restarting the application. - Adicionar {0} a um tipo genérico requer o reinício do aplicativo. - - Adding {0} into an interface method requires restarting the application. Adicionar {0} a um método de interface requer a reinicialização do aplicativo. @@ -140,11 +135,6 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Adicionar um construtor a um tipo com um inicializador de campo ou propriedade que contém uma função anônima requer a reinicialização do aplicativo. - - Adding a generic {0} requires restarting the application. - Adicionar um {0} genérico requer o reinício do aplicativo. - - Adding a method with an explicit interface specifier requires restarting the application. Adicionar um método com um especificador de interface explícito requer o reinício do aplicativo. @@ -1200,21 +1190,6 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Modificar a origem com recursos de linguagem experimental habilitados requer a reinicialização do aplicativo. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Modificar o inicializador de {0} em um tipo genérico requer a reinicialização do aplicativo. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - A modificação de espaços em branco ou comentários em {0} dentro do contexto de um tipo genérico requer o reinício do aplicativo. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - A modificação de espaços em branco ou comentários em um {0} genérico requer a reinicialização do aplicativo. - - Move contents to namespace... Mover conteúdo para o namespace... @@ -2830,6 +2805,11 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas Atualizar '{0}' requer reiniciar o aplicativo. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Atualizar um {0} em torno de uma instrução ativa requer a reinicialização do aplicativo. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index 1ecd51c375abc..90a8e079155bb 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -100,11 +100,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Для добавления {0} в класс с явным или последовательным макетом требуется перезапустить приложение. - - Adding {0} into a generic type requires restarting the application. - Для добавления {0} в универсальный тип требуется перезапустить приложение. - - Adding {0} into an interface method requires restarting the application. Для добавления {0} в метод интерфейса требуется перезапустить приложение. @@ -140,11 +135,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Для добавления конструктора к типу с инициализатором поля или свойства, содержащим анонимную функцию, требуется перезапустить приложение. - - Adding a generic {0} requires restarting the application. - Для добавления универсального {0} требуется перезапустить приложение. - - Adding a method with an explicit interface specifier requires restarting the application. Для добавления метода с явным описателем интерфейса требуется перезапустить приложение. @@ -1200,21 +1190,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Для изменения исходного кода с включенными экспериментальными функциями языка требуется перезапустить приложение.. - - Modifying the initializer of {0} in a generic type requires restarting the application. - Для изменения инициализатора {0} универсального типа требуется перезапустить приложение. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Для изменения пустого пространства или комментариев в {0} в контексте универсального типа требуется перезапустить приложение. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Для изменения пустого пространства или комментариев в универсальном {0} требуется перезапустить приложение. - - Move contents to namespace... Переместить содержимое в пространство имен... @@ -2830,6 +2805,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Для обновления "{0}" требуется перезапустить приложение. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Для обновления {0} вокруг активного оператора требуется перезапустить приложение. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 423e99126879e..a890064d01044 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -100,11 +100,6 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Açık veya sıralı düzene sahip bir sınıfa {0} eklemek, uygulamanın yeniden başlatılmasını gerektirir. - - Adding {0} into a generic type requires restarting the application. - Genel bir türe {0} eklenmesi, uygulamanın yeniden başlatılmasını gerektirir. - - Adding {0} into an interface method requires restarting the application. Bir arabirim yöntemine {0} eklemek, uygulamanın yeniden başlatılmasını gerektirir. @@ -140,11 +135,6 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Anonim bir tür içeren alan veya özellik başlatıcısının bulunduğu bir türe oluşturucu eklenmesi, uygulamanın yeniden başlatılmasını gerektirir. - - Adding a generic {0} requires restarting the application. - Genel bir {0} eklemek için uygulamanın yeniden başlatılması gerekir. - - Adding a method with an explicit interface specifier requires restarting the application. Açık bir arabirim tanımlayıcısıyla bir yöntem eklemek, uygulamanın yeniden başlatılmasını gerektirir. @@ -1200,21 +1190,6 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Deneysel dil özellikleri etkinken kaynağı değiştirme, uygulamanın yeniden başlatılmasını gerektirir. - - Modifying the initializer of {0} in a generic type requires restarting the application. - {0} öğesinin başlatıcısının genel bir türde değiştirilmesi, uygulamanın yeniden başlatılmasını gerektirir. - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - Genel bir tür bağlamında {0} öğesindeki boşlukların veya yorumların değiştirilmesi, uygulamanın yeniden başlatılmasını gerektirir. - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - Genel bir {0} öğesindeki boşlukların veya yorumları değiştirilmesi, uygulamanın yeniden başlatılmasını gerektirir. - - Move contents to namespace... İçerikleri ad alanına taşı... @@ -2830,6 +2805,11 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri {0} öğesinin güncelleştirilmesi, uygulamanın yeniden başlatılmasını gerektirir. + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. Etkin bir deyim etrafında bir {0} güncelleştirmesi, uygulamanın yeniden başlatılmasını gerektirir. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index bdef208b6e923..f20d3350000a9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -100,11 +100,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 将 {0} 添加到具有显式或顺序布局的类中需要重新启动应用程序。 - - Adding {0} into a generic type requires restarting the application. - 向泛型类型添加 {0} 需要重启应用程序。 - - Adding {0} into an interface method requires restarting the application. 将 {0} 添加到接口方法中需要重新启动应用程序。 @@ -140,11 +135,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 使用包含匿名类型的字段或属性初始值设定项向类型添加构造函数需要重新启动应用程序。 - - Adding a generic {0} requires restarting the application. - 添加泛型 {0} 要求重启应用程序。 - - Adding a method with an explicit interface specifier requires restarting the application. 添加具有显式接口说明符的方法需要重启应用程序。 @@ -1200,21 +1190,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 在启用实验语言功能的情况下修改源需要重新启动应用程序。 - - Modifying the initializer of {0} in a generic type requires restarting the application. - 在泛型类型中修改 {0} 的初始化表达式需要重启应用程序。 - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - 修改泛型类型上下文内 {0} 中空格或注释需要重启应用程序。 - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - 修改泛型 {0} 中的空格或注释需要重启应用程序。 - - Move contents to namespace... 将内容移动到命名空间... @@ -2830,6 +2805,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of 更新“{0}”需要重启应用程序。 + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. 更新活动语句周围的 {0} 需要重新启动应用程序。 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 723823d5cc68c..5120a7b6c0e3e 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -100,11 +100,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 在具有明確或循序配置的類別中新增 {0} 需要重新啟動應用程式。 - - Adding {0} into a generic type requires restarting the application. - 在泛型型別中新增 {0} 需要重新啟動應用程式。 - - Adding {0} into an interface method requires restarting the application. 在介面方法中新增 {0} 需要重新啟動應用程式。 @@ -140,11 +135,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 使用包含匿名函式的欄位或屬性初始設定式,將建構函式新增至類型需要重新啟動應用程式。 - - Adding a generic {0} requires restarting the application. - 新增一般 {0} 需要重新啟動應用程式。 - - Adding a method with an explicit interface specifier requires restarting the application. 新增具有明確介面指定名稱的方法需要重新啟動應用程式。 @@ -1200,21 +1190,6 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 以啟用的實驗語言功能修改原始檔,需要重新啟動應用程式。 - - Modifying the initializer of {0} in a generic type requires restarting the application. - 修改泛型型別中 {0} 的初始設定式需要重新啟動應用程式。 - - - - Modifying whitespace or comments in {0} inside the context of a generic type requires restarting the application. - 修改泛型型別内容 {0} 中的空白或註解需要重新啟動應用程式。 - - - - Modifying whitespace or comments in a generic {0} requires restarting the application. - 修改泛型 {0} 中的空白或註解需要重新啟動應用程式。 - - Move contents to namespace... 將內容移到命名空間... @@ -2830,6 +2805,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of 更新 '{0}' 需要重新啟動應用程式。 + + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + Updating {0} within generic type or method requires restarting the application because is not supported by the runtime. + + Updating a {0} around an active statement requires restarting the application. 更新作用中陳述式前後的 {0} 需要重新啟動應用程式。 diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs index 4d6971b70a2c8..e81f86e1b666d 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs @@ -299,6 +299,13 @@ public async Task TryGetAsync(ArrayBuilder list, Cancellat if (analyzer is DocumentDiagnosticAnalyzer) return true; + // Special case GeneratorDiagnosticsPlaceholderAnalyzer to never skip it based on + // 'shouldIncludeDiagnostic' predicate. More specifically, this is a placeholder analyzer + // for threading through all source generator reported diagnostics, but this special analyzer + // reports 0 supported diagnostics, and we always want to execute it. + if (analyzer is GeneratorDiagnosticsPlaceholderAnalyzer) + return true; + // Skip analyzer if none of its reported diagnostics should be included. if (shouldIncludeDiagnostic != null && !owner.DiagnosticAnalyzerInfoCache.GetDiagnosticDescriptors(analyzer).Any(static (a, shouldIncludeDiagnostic) => shouldIncludeDiagnostic(a.Id), shouldIncludeDiagnostic)) diff --git a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs index 317729d1b6abb..81fa6b846b82e 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs @@ -16,7 +16,8 @@ public static WorkspaceConfigurationOptions GetWorkspaceConfigurationOptions(thi EnableOpeningSourceGeneratedFiles: globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspace) ?? globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag), DisableSharedSyntaxTrees: globalOptions.GetOption(DisableSharedSyntaxTrees), - DeferCreatingRecoverableText: globalOptions.GetOption(DeferCreatingRecoverableText)); + DeferCreatingRecoverableText: globalOptions.GetOption(DeferCreatingRecoverableText), + DisableRecoverableText: globalOptions.GetOption(DisableRecoverableText)); public static readonly Option2 Database = new( "dotnet_storage_database", WorkspaceConfigurationOptions.Default.CacheStorage, serializer: EditorConfigValueSerializer.CreateSerializerForEnum()); @@ -30,6 +31,9 @@ public static WorkspaceConfigurationOptions GetWorkspaceConfigurationOptions(thi public static readonly Option2 DeferCreatingRecoverableText = new( "dotnet_defer_creating_recoverable_text", WorkspaceConfigurationOptions.Default.DeferCreatingRecoverableText); + public static readonly Option2 DisableRecoverableText = new( + "dotnet_disable_recoverable_text", WorkspaceConfigurationOptions.Default.DisableRecoverableText); + /// /// This option allows the user to enable this. We are putting this behind a feature flag for now since we could have extensions /// surprised by this and we want some time to work through those issues. diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensCache.cs b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensCache.cs deleted file mode 100644 index 5ae1c03dad1c5..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensCache.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Immutable; -using Microsoft.CodeAnalysis.CodeLens; -using Microsoft.CodeAnalysis.Text; -using Microsoft.VisualStudio.LanguageServer.Protocol; -using static Microsoft.CodeAnalysis.LanguageServer.Handler.CodeLens.CodeLensCache; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeLens; - -internal sealed class CodeLensCache : ResolveCache -{ - /// - /// Use a cache size of 3 as a rough baseline - generally 1 is enough - /// however there are certain edge cases (like quickly switching active documents) - /// where a resolve request could be made for an older textDocument/codelens request. - /// - /// If we discover this number is too low, we can adjust in the future. - /// - public CodeLensCache() : base(maxCacheSize: 3) - { - } - - /// - /// Cached data need to resolve a specific code lens item - /// - /// the list of nodes and locations for codelens members - /// the syntax version the codelenses were calculated against (to validate the resolve request) - internal record CodeLensCacheEntry(ImmutableArray CodeLensMembers, VersionStamp SyntaxVersion); -} diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensCacheFactory.cs b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensCacheFactory.cs deleted file mode 100644 index e00a64ec8c080..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensCacheFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeLens; - -[ExportCSharpVisualBasicLspServiceFactory(typeof(CodeLensCache)), Shared] -internal class CodeLensCacheFactory : ILspServiceFactory -{ - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CodeLensCacheFactory() - { - } - - public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) => new CodeLensCache(); -} diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensHandler.cs b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensHandler.cs index 5afc072fbb3ed..96c0c6b3d0b54 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensHandler.cs @@ -45,12 +45,6 @@ public LSP.TextDocumentIdentifier GetTextDocumentIdentifier(LSP.CodeLensParams r var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var syntaxVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); - var codeLensCache = context.GetRequiredLspService(); - - // Store the members in the resolve cache so that when we get a resolve request for a particular - // member we can re-use the syntax node and span we already computed here. - var resultId = codeLensCache.UpdateCache(new CodeLensCache.CodeLensCacheEntry(members, syntaxVersion)); - // TODO - Code lenses need to be refreshed by the server when we detect solution/project wide changes. // See https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1730462 @@ -63,7 +57,7 @@ public LSP.TextDocumentIdentifier GetTextDocumentIdentifier(LSP.CodeLensParams r { Range = range, Command = null, - Data = new CodeLensResolveData(resultId, i, request.TextDocument) + Data = new CodeLensResolveData(syntaxVersion.ToString(), i, request.TextDocument) }; codeLenses.Add(codeLens); diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveData.cs b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveData.cs index fe5277d58c335..312bd6800008d 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveData.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveData.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeLens; /// /// Datatype storing the information needed to resolve a particular code lens item. /// -/// the resultId associated with the code lens list created on original request. +/// the syntax version of the text document. /// the index of the specific code lens item in the original list. /// the text document associated with the code lens to resolve. -internal sealed record CodeLensResolveData(long ResultId, int ListIndex, TextDocumentIdentifier TextDocument); +internal sealed record CodeLensResolveData(string SyntaxVersion, int ListIndex, TextDocumentIdentifier TextDocument); diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandler.cs b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandler.cs index 67fe0f22bc148..fc65f3f04a01d 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandler.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using Roslyn.Utilities; using StreamJsonRpc; +using Microsoft.CodeAnalysis.Shared.Extensions; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.CodeLens; @@ -21,11 +22,8 @@ internal sealed class CodeLensResolveHandler : ILspServiceDocumentRequestHandler /// private const string ClientReferencesCommand = "roslyn.client.peekReferences"; - private readonly CodeLensCache _codeLensCache; - - public CodeLensResolveHandler(CodeLensCache codeLensCache) + public CodeLensResolveHandler() { - _codeLensCache = codeLensCache; } public bool MutatesSolutionState => false; @@ -38,8 +36,8 @@ public LSP.TextDocumentIdentifier GetTextDocumentIdentifier(LSP.CodeLens request public async Task HandleRequestAsync(LSP.CodeLens request, RequestContext context, CancellationToken cancellationToken) { var document = context.GetRequiredDocument(); + var currentDocumentSyntaxVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); var resolveData = GetCodeLensResolveData(request); - var (cacheEntry, memberToResolve) = GetCacheEntry(resolveData); request.Command = new LSP.Command { @@ -52,32 +50,37 @@ public async Task HandleRequestAsync(LSP.CodeLens request, Request } }; - var currentSyntaxVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false); - var cachedSyntaxVersion = cacheEntry.SyntaxVersion; - - if (currentSyntaxVersion != cachedSyntaxVersion) + // If the request is for an older version of the document, return a request with '- references' + if (resolveData.SyntaxVersion != currentDocumentSyntaxVersion.ToString()) { - context.TraceInformation($"Cached resolve version {cachedSyntaxVersion} does not match current version {currentSyntaxVersion}"); + context.TraceInformation($"Requested syntax version {resolveData.SyntaxVersion} does not match current version {currentDocumentSyntaxVersion}"); return request; } + var codeLensMemberFinder = document.GetRequiredLanguageService(); + var members = await codeLensMemberFinder.GetCodeLensMembersAsync(document, cancellationToken).ConfigureAwait(false); + + var memberToResolve = members[resolveData.ListIndex]; var codeLensReferencesService = document.Project.Solution.Services.GetRequiredService(); var referenceCount = await codeLensReferencesService.GetReferenceCountAsync(document.Project.Solution, document.Id, memberToResolve.Node, maxSearchResults: 99, cancellationToken).ConfigureAwait(false); if (referenceCount != null) { - request.Command.Title = referenceCount.Value.GetDescription(); + request.Command = new LSP.Command + { + Title = referenceCount.Value.GetDescription(), + CommandIdentifier = ClientReferencesCommand, + Arguments = new object[] + { + resolveData.TextDocument.Uri, + request.Range.Start + } + }; + } return request; } - private (CodeLensCache.CodeLensCacheEntry CacheEntry, CodeLensMember MemberToResolve) GetCacheEntry(CodeLensResolveData resolveData) - { - var cacheEntry = _codeLensCache.GetCachedEntry(resolveData.ResultId); - Contract.ThrowIfNull(cacheEntry, "Missing cache entry for code lens resolve request"); - return (cacheEntry, cacheEntry.CodeLensMembers[resolveData.ListIndex]); - } - private static CodeLensResolveData GetCodeLensResolveData(LSP.CodeLens codeLens) { var resolveData = (codeLens.Data as JToken)?.ToObject(); diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandlerFactory.cs b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandlerFactory.cs index c490bb650e0b0..f067e3aa69bf3 100644 --- a/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandlerFactory.cs +++ b/src/Features/LanguageServer/Protocol/Handler/CodeLens/CodeLensResolveHandlerFactory.cs @@ -19,8 +19,7 @@ public CodeLensResolveHandlerFactory() public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind) { - var completionListCache = lspServices.GetRequiredService(); - return new CodeLensResolveHandler(completionListCache); + return new CodeLensResolveHandler(); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs b/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs index b2332da3473ce..eb7b9fdb87254 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs @@ -26,6 +26,7 @@ internal partial class DidChangeConfigurationNotificationHandler ImplementTypeOptionsStorage.PropertyGenerationBehavior, // Completion CompletionOptionsStorage.ShowNameSuggestions, + CompletionOptionsStorage.ShowItemsFromUnimportedNamespaces, CompletionOptionsStorage.ProvideRegexCompletions, QuickInfoOptionsStorage.ShowRemarksInQuickInfo, // Go to definition diff --git a/src/Features/LanguageServer/ProtocolUnitTests/CodeLens/CSharpCodeLensTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/CodeLens/CSharpCodeLensTests.cs index 847daa07110ba..f57e63f8685bc 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/CodeLens/CSharpCodeLensTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/CodeLens/CSharpCodeLensTests.cs @@ -195,7 +195,7 @@ public async Task TestRecordDeclarationAsync(bool lspMutatingWorkspace) } [Theory, CombinatorialData] - public async Task TestDoesNotShutdownServerIfCacheEntryMissing(bool mutatingLspWorkspace) + public async Task TestDoesNotCrashWhenSyntaxVersionsMismatch(bool mutatingLspWorkspace) { var markup = @"class A @@ -209,38 +209,26 @@ void UseM() M(); } }"; + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace); - var textDocument = CreateTextDocumentIdentifier(testLspServer.GetCurrentSolution().Projects.Single().Documents.Single().GetURI()); - var codeLensParams = new LSP.CodeLensParams + var documentUri = testLspServer.GetCurrentSolution().Projects.Single().Documents.Single().GetURI(); + var codeLensParamsDoc1 = new LSP.CodeLensParams { - TextDocument = textDocument + TextDocument = CreateTextDocumentIdentifier(documentUri) }; - var actualCodeLenses = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCodeLensName, codeLensParams, CancellationToken.None); + var actualCodeLenses = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCodeLensName, codeLensParamsDoc1, CancellationToken.None); var firstCodeLens = actualCodeLenses.First(); var data = JsonConvert.DeserializeObject(firstCodeLens.Data!.ToString()); AssertEx.NotNull(data); - var firstResultId = data.ResultId; - - // Verify the code lens item is in the cache. - var cache = testLspServer.GetRequiredLspService(); - Assert.NotNull(cache.GetCachedEntry(firstResultId)); - - // Execute a few more requests to ensure the first request is removed from the cache. - await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCodeLensName, codeLensParams, CancellationToken.None); - await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCodeLensName, codeLensParams, CancellationToken.None); - var lastCodeLenses = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCodeLensName, codeLensParams, CancellationToken.None); - Assert.True(lastCodeLenses.Any()); - - // Assert that the first result id is no longer in the cache. - Assert.Null(cache.GetCachedEntry(firstResultId)); - // Assert that the request throws because the item no longer exists in the cache. - await Assert.ThrowsAsync(async () => await testLspServer.ExecuteRequestAsync(LSP.Methods.CodeLensResolveName, firstCodeLens, CancellationToken.None)); + // Update the document so the syntax version changes + await testLspServer.OpenDocumentAsync(documentUri); + await testLspServer.InsertTextAsync(documentUri, (0, 0, "A")); - // Assert that the server did not shutdown and that we can resolve the latest codelens request we made. - var lastCodeLens = await testLspServer.ExecuteRequestAsync(LSP.Methods.CodeLensResolveName, lastCodeLenses.First(), CancellationToken.None); - Assert.NotNull(lastCodeLens?.Command); + // Assert that we don't crash when sending an old request to a new document + var firstDocumentResult2 = await testLspServer.ExecuteRequestAsync(LSP.Methods.CodeLensResolveName, firstCodeLens, CancellationToken.None); + Assert.NotNull(firstDocumentResult2?.Command?.Title); } } diff --git a/src/Tools/ExternalAccess/Debugger/GlassTestsHotReloadService.cs b/src/Tools/ExternalAccess/Debugger/GlassTestsHotReloadService.cs index 7179e650ac0c3..3018e8c5fd72e 100644 --- a/src/Tools/ExternalAccess/Debugger/GlassTestsHotReloadService.cs +++ b/src/Tools/ExternalAccess/Debugger/GlassTestsHotReloadService.cs @@ -19,12 +19,12 @@ internal sealed class GlassTestsHotReloadService private readonly IManagedHotReloadService _debuggerService; - private readonly IEditAndContinueWorkspaceService _encService; + private readonly IEditAndContinueService _encService; private DebuggingSessionId _sessionId; public GlassTestsHotReloadService(HostWorkspaceServices services, IManagedHotReloadService debuggerService) { - _encService = services.GetRequiredService(); + _encService = services.GetRequiredService().Service; _debuggerService = debuggerService; } diff --git a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs index a980c84129ede..4ae1a89071acd 100644 --- a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs +++ b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs @@ -427,6 +427,7 @@ public bool TryFetch(LocalUserRegistryOptionPersister persister, OptionKey2 opti {"visual_studio_workspace_partial_load_mode", new FeatureFlagStorage(@"Roslyn.PartialLoadMode")}, {"dotnet_disable_shared_syntax_trees", new FeatureFlagStorage(@"Roslyn.DisableSharedSyntaxTrees")}, {"dotnet_defer_creating_recoverable_text", new FeatureFlagStorage(@"Roslyn.DeferCreatingRecoverableText")}, + {"dotnet_disable_recoverable_text", new FeatureFlagStorage(@"Roslyn.DisableRecoverableText")}, {"dotnet_enable_diagnostics_in_source_generated_files", new RoamingProfileStorage("TextEditor.Roslyn.Specific.EnableDiagnosticsInSourceGeneratedFilesExperiment")}, {"dotnet_enable_diagnostics_in_source_generated_files_feature_flag", new FeatureFlagStorage(@"Roslyn.EnableDiagnosticsInSourceGeneratedFiles")}, {"dotnet_enable_opening_source_generated_files_in_workspace", new RoamingProfileStorage("TextEditor.Roslyn.Specific.EnableOpeningSourceGeneratedFilesInWorkspaceExperiment")}, diff --git a/src/Workspaces/Core/Portable/Workspace/IWorkspaceConfigurationService.cs b/src/Workspaces/Core/Portable/Workspace/IWorkspaceConfigurationService.cs index 866196384b908..a966c424d5dbb 100644 --- a/src/Workspaces/Core/Portable/Workspace/IWorkspaceConfigurationService.cs +++ b/src/Workspaces/Core/Portable/Workspace/IWorkspaceConfigurationService.cs @@ -41,7 +41,8 @@ public DefaultWorkspaceConfigurationService() [property: DataMember(Order = 0)] StorageDatabase CacheStorage = StorageDatabase.SQLite, [property: DataMember(Order = 1)] bool EnableOpeningSourceGeneratedFiles = false, [property: DataMember(Order = 2)] bool DisableSharedSyntaxTrees = false, - [property: DataMember(Order = 3)] bool DeferCreatingRecoverableText = false) + [property: DataMember(Order = 3)] bool DeferCreatingRecoverableText = false, + [property: DataMember(Order = 4)] bool DisableRecoverableText = false) { public WorkspaceConfigurationOptions() : this(CacheStorage: StorageDatabase.SQLite) @@ -58,6 +59,7 @@ public WorkspaceConfigurationOptions() CacheStorage: StorageDatabase.None, EnableOpeningSourceGeneratedFiles: false, DisableSharedSyntaxTrees: false, - DeferCreatingRecoverableText: false); + DeferCreatingRecoverableText: false, + DisableRecoverableText: false); } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs index 5a8949d62b57c..21f236205b432 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState.cs @@ -79,11 +79,14 @@ private static ITextAndVersionSource CreateStrongText(TextLoader loader) private static ITextAndVersionSource CreateRecoverableText(TextAndVersion text, LoadTextOptions loadTextOptions, SolutionServices services) { - var result = new RecoverableTextAndVersion(new ConstantTextAndVersionSource(text), services); - var service = services.GetRequiredService(); var options = service.Options; + if (options.DisableRecoverableText) + return CreateStrongText(text); + + var result = new RecoverableTextAndVersion(new ConstantTextAndVersionSource(text), services); + if (!options.DeferCreatingRecoverableText) { // This RecoverableTextAndVersion is created directly from a TextAndVersion instance. In its initial state, @@ -99,7 +102,15 @@ private static ITextAndVersionSource CreateRecoverableText(TextAndVersion text, } private static ITextAndVersionSource CreateRecoverableText(TextLoader loader, SolutionServices services) - => new RecoverableTextAndVersion(new LoadableTextAndVersionSource(loader, cacheResult: false), services); + { + var service = services.GetRequiredService(); + var options = service.Options; + + if (options.DisableRecoverableText) + return CreateStrongText(loader); + + return new RecoverableTextAndVersion(new LoadableTextAndVersionSource(loader, cacheResult: false), services); + } public ITemporaryTextStorageInternal? Storage => (TextAndVersionSource as RecoverableTextAndVersion)?.Storage; diff --git a/src/Workspaces/CoreTestUtilities/Remote/InProcRemoteHostClientProvider.cs b/src/Workspaces/CoreTestUtilities/Remote/InProcRemoteHostClientProvider.cs index 57c799411bca4..7f6cfb699835d 100644 --- a/src/Workspaces/CoreTestUtilities/Remote/InProcRemoteHostClientProvider.cs +++ b/src/Workspaces/CoreTestUtilities/Remote/InProcRemoteHostClientProvider.cs @@ -35,15 +35,22 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) private sealed class WorkspaceManager : RemoteWorkspaceManager { - public WorkspaceManager(Func createAssetStorage, ConcurrentDictionary sharedTestGeneratorReferences, Type[]? additionalRemoteParts) - : base(createAssetStorage, CreateRemoteWorkspace(sharedTestGeneratorReferences, additionalRemoteParts)) + public WorkspaceManager( + Func createAssetStorage, + ConcurrentDictionary sharedTestGeneratorReferences, + Type[]? additionalRemoteParts, + Type[]? excludedRemoteParts) + : base(createAssetStorage, CreateRemoteWorkspace(sharedTestGeneratorReferences, additionalRemoteParts, excludedRemoteParts)) { } } - private static RemoteWorkspace CreateRemoteWorkspace(ConcurrentDictionary sharedTestGeneratorReferences, Type[]? additionalRemoteParts) + private static RemoteWorkspace CreateRemoteWorkspace( + ConcurrentDictionary sharedTestGeneratorReferences, + Type[]? additionalRemoteParts, + Type[]? excludedRemoteParts) { - var hostServices = FeaturesTestCompositions.RemoteHost.AddParts(additionalRemoteParts).GetHostServices(); + var hostServices = FeaturesTestCompositions.RemoteHost.AddParts(additionalRemoteParts).AddExcludedPartTypes(excludedRemoteParts).GetHostServices(); // We want to allow references to source generators to be shared between the "in proc" and "remote" workspaces and // MEF compositions, so tell the serializer service to use the same map for this "remote" workspace as the in-proc one. @@ -56,6 +63,7 @@ private static RemoteWorkspace CreateRemoteWorkspace(ConcurrentDictionary _lazyClient; public Type[]? AdditionalRemoteParts { get; set; } + public Type[]? ExcludedRemoteParts { get; set; } public TraceListener? TraceListener { get; set; } public InProcRemoteHostClientProvider(SolutionServices services, RemoteServiceCallbackDispatcherRegistry callbackDispatchers) @@ -68,7 +76,8 @@ public InProcRemoteHostClientProvider(SolutionServices services, RemoteServiceCa () => new WorkspaceManager( _ => new SolutionAssetCache(), testSerializerServiceFactory.SharedTestGeneratorReferences, - AdditionalRemoteParts)); + AdditionalRemoteParts, + ExcludedRemoteParts)); _lazyClient = new Lazy( () => InProcRemoteHostClient.Create( _services, diff --git a/src/Workspaces/Remote/ServiceHub/Services/EditAndContinue/RemoteEditAndContinueService.cs b/src/Workspaces/Remote/ServiceHub/Services/EditAndContinue/RemoteEditAndContinueService.cs index d06b9e91ccf64..6e6494a8d1942 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/EditAndContinue/RemoteEditAndContinueService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/EditAndContinue/RemoteEditAndContinueService.cs @@ -73,8 +73,8 @@ public RemoteEditAndContinueService(in ServiceConstructionArguments arguments, R _callback = callback; } - private IEditAndContinueWorkspaceService GetService() - => GetWorkspace().Services.GetRequiredService(); + private IEditAndContinueService GetService() + => GetWorkspace().Services.GetRequiredService().Service; private ActiveStatementSpanProvider CreateActiveStatementSpanProvider(RemoteServiceCallbackId callbackId) => new((documentId, filePath, cancellationToken) => _callback.InvokeAsync((callback, cancellationToken) => callback.GetSpansAsync(callbackId, documentId, filePath, cancellationToken), cancellationToken)); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/DiagnosticDescriptorExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/DiagnosticDescriptorExtensions.cs index eada350447e61..98d98c90e7b6c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/DiagnosticDescriptorExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/DiagnosticDescriptorExtensions.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using System.Threading; using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.CodeAnalysis.Shared.Extensions @@ -55,6 +56,44 @@ public static ImmutableArray ImmutableCustomTags(this DiagnosticDescript return effectiveSeverity; } + /// + /// Gets document-level effective severity of the given accounting for severity configurations from both the following sources: + /// 1. Compilation options from ruleset file, if any, and command line options such as /nowarn, /warnaserror, etc. + /// 2. Analyzer config documents at the document root directory or in ancestor directories. + /// + public static ReportDiagnostic GetEffectiveSeverity(this DiagnosticDescriptor descriptor, CompilationOptions compilationOptions, SyntaxTree tree, AnalyzerOptions analyzerOptions) + { + var effectiveSeverity = descriptor.GetEffectiveSeverity(compilationOptions); + + // Apply analyzer config options, unless configured with a non-default value in compilation options. + // Note that compilation options (/nowarn, /warnaserror) override analyzer config options. + if (!compilationOptions.SpecificDiagnosticOptions.TryGetValue(descriptor.Id, out var reportDiagnostic) || + reportDiagnostic == ReportDiagnostic.Default) + { + // First check for tree-level analyzer config options. + var analyzerConfigOptions = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(tree); + var providerAndTree = compilationOptions.SyntaxTreeOptionsProvider != null + ? (compilationOptions.SyntaxTreeOptionsProvider, tree) + : default; + var severityInEditorConfig = descriptor.GetEffectiveSeverity(analyzerConfigOptions, providerAndTree); + if (severityInEditorConfig != ReportDiagnostic.Default) + { + effectiveSeverity = severityInEditorConfig; + } + else + { + // If not found, check for global analyzer config options. + var severityInGlobalConfig = descriptor.GetEffectiveSeverity(analyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions, providerAndTree); + if (severityInGlobalConfig != ReportDiagnostic.Default) + { + effectiveSeverity = severityInGlobalConfig; + } + } + } + + return effectiveSeverity; + } + public static bool IsDefinedInEditorConfig(this DiagnosticDescriptor descriptor, AnalyzerConfigOptions analyzerConfigOptions) { // Check if the option is defined explicitly in the editorconfig @@ -97,14 +136,39 @@ public static bool IsDefinedInEditorConfig(this DiagnosticDescriptor descriptor, return false; } - public static ReportDiagnostic GetEffectiveSeverity(this DiagnosticDescriptor descriptor, AnalyzerConfigOptions analyzerConfigOptions) + /// + /// Gets the effective diagnostic severity for the diagnostic ID corresponding to the + /// given by looking up the severity settings in the options. + /// If the provided options are specific to a particular tree, provide a non-null value + /// for to look up tree specific severity options. + /// + public static ReportDiagnostic GetEffectiveSeverity( + this DiagnosticDescriptor descriptor, + AnalyzerConfigOptions analyzerConfigOptions, + (SyntaxTreeOptionsProvider provider, SyntaxTree tree)? providerAndTree = null) { + ReportDiagnostic severity; + string? value; + // Check if the option is defined explicitly in the editorconfig - var diagnosticKey = $"{DotnetDiagnosticPrefix}.{descriptor.Id}.{SeveritySuffix}"; - if (analyzerConfigOptions.TryGetValue(diagnosticKey, out var value) && - EditorConfigSeverityStrings.TryParse(value, out var severity)) + if (providerAndTree.HasValue) { - return severity; + var provider = providerAndTree.Value.provider; + var tree = providerAndTree.Value.tree; + if (provider.TryGetDiagnosticValue(tree, descriptor.Id, CancellationToken.None, out severity) || + provider.TryGetGlobalDiagnosticValue(descriptor.Id, CancellationToken.None, out severity)) + { + return severity; + } + } + else + { + var diagnosticKey = $"{DotnetDiagnosticPrefix}.{descriptor.Id}.{SeveritySuffix}"; + if (analyzerConfigOptions.TryGetValue(diagnosticKey, out value) && + EditorConfigSeverityStrings.TryParse(value, out severity)) + { + return severity; + } } // Check if the option is defined as part of a bulk configuration From 0c21c57878f745289946df71aab0434043531047 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Wed, 26 Apr 2023 11:12:53 -0700 Subject: [PATCH 196/261] Add missing rename service --- .../Microsoft.CodeAnalysis.Features.csproj | 1 + ...eActionOperationFactoryWorkspaceService.cs | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 3b57a428d8359..0bf24142cafac 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -83,6 +83,7 @@ + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs new file mode 100644 index 0000000000000..76bb62f588bbd --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Composition; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeActions.WorkspaceServices; +using Microsoft.CodeAnalysis.Host.Mef; + +namespace Microsoft.CodeAnalysis.LanguageServer.Services.Rename +{ + [ExportWorkspaceService(typeof(ISymbolRenamedCodeActionOperationFactoryWorkspaceService), ServiceLayer.Host), Shared] + internal class LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService : ISymbolRenamedCodeActionOperationFactoryWorkspaceService + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService() + { + } + + public CodeActionOperation CreateSymbolRenamedOperation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution) + => new RenameCodeActionOperation( + title: string.Format(WorkspacesResources.Rename_0_to_1, symbol.Name, newName), + updateSolution: updatedSolution); + + private class RenameCodeActionOperation : CodeActionOperation + { + private readonly string _title; + private readonly Solution _updateSolution; + + public RenameCodeActionOperation(string title, Solution updateSolution) + { + _title = title; + _updateSolution = updateSolution; + } + + public override void Apply(Workspace workspace, CancellationToken cancellationToken = default) + => workspace.TryApplyChanges(_updateSolution); + + public override string? Title => _title; + } + } +} From 6a8d498a5712ad4f646c7ef29f279fb490943faa Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Wed, 26 Apr 2023 11:49:29 -0700 Subject: [PATCH 197/261] Change the ApplyChangesOperation --- ...eActionOperationFactoryWorkspaceService.cs | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs index 76bb62f588bbd..d656ebe8fcd50 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs @@ -24,25 +24,6 @@ public LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService() } public CodeActionOperation CreateSymbolRenamedOperation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution) - => new RenameCodeActionOperation( - title: string.Format(WorkspacesResources.Rename_0_to_1, symbol.Name, newName), - updateSolution: updatedSolution); - - private class RenameCodeActionOperation : CodeActionOperation - { - private readonly string _title; - private readonly Solution _updateSolution; - - public RenameCodeActionOperation(string title, Solution updateSolution) - { - _title = title; - _updateSolution = updateSolution; - } - - public override void Apply(Workspace workspace, CancellationToken cancellationToken = default) - => workspace.TryApplyChanges(_updateSolution); - - public override string? Title => _title; - } + => new ApplyChangesOperation(updatedSolution); } } From d98cb4836964e50c7de6ce4494c0b5078cea064a Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Wed, 26 Apr 2023 12:22:03 -0700 Subject: [PATCH 198/261] Revert "Change the ApplyChangesOperation" This reverts commit 6a8d498a5712ad4f646c7ef29f279fb490943faa. --- ...eActionOperationFactoryWorkspaceService.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs index d656ebe8fcd50..76bb62f588bbd 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs @@ -24,6 +24,25 @@ public LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService() } public CodeActionOperation CreateSymbolRenamedOperation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution) - => new ApplyChangesOperation(updatedSolution); + => new RenameCodeActionOperation( + title: string.Format(WorkspacesResources.Rename_0_to_1, symbol.Name, newName), + updateSolution: updatedSolution); + + private class RenameCodeActionOperation : CodeActionOperation + { + private readonly string _title; + private readonly Solution _updateSolution; + + public RenameCodeActionOperation(string title, Solution updateSolution) + { + _title = title; + _updateSolution = updateSolution; + } + + public override void Apply(Workspace workspace, CancellationToken cancellationToken = default) + => workspace.TryApplyChanges(_updateSolution); + + public override string? Title => _title; + } } } From 94dc877a79e186da7f8a8e7f2427fefa414ea7d5 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Wed, 26 Apr 2023 12:22:05 -0700 Subject: [PATCH 199/261] Revert "Add missing rename service" This reverts commit 0c21c57878f745289946df71aab0434043531047. --- .../Microsoft.CodeAnalysis.Features.csproj | 1 - ...eActionOperationFactoryWorkspaceService.cs | 48 ------------------- 2 files changed, 49 deletions(-) delete mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 0bf24142cafac..3b57a428d8359 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -83,7 +83,6 @@ - diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs deleted file mode 100644 index 76bb62f588bbd..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Rename/LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Composition; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeActions.WorkspaceServices; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.LanguageServer.Services.Rename -{ - [ExportWorkspaceService(typeof(ISymbolRenamedCodeActionOperationFactoryWorkspaceService), ServiceLayer.Host), Shared] - internal class LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService : ISymbolRenamedCodeActionOperationFactoryWorkspaceService - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public LanguageServerSymbolRenamedCodeActionOperationFactoryWorkspaceService() - { - } - - public CodeActionOperation CreateSymbolRenamedOperation(ISymbol symbol, string newName, Solution startingSolution, Solution updatedSolution) - => new RenameCodeActionOperation( - title: string.Format(WorkspacesResources.Rename_0_to_1, symbol.Name, newName), - updateSolution: updatedSolution); - - private class RenameCodeActionOperation : CodeActionOperation - { - private readonly string _title; - private readonly Solution _updateSolution; - - public RenameCodeActionOperation(string title, Solution updateSolution) - { - _title = title; - _updateSolution = updateSolution; - } - - public override void Apply(Workspace workspace, CancellationToken cancellationToken = default) - => workspace.TryApplyChanges(_updateSolution); - - public override string? Title => _title; - } - } -} From 93f8a8c033636a798d6601e39eebfa4f3e7459af Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Wed, 26 Apr 2023 12:26:18 -0700 Subject: [PATCH 200/261] Make change based on if the service is provided or not --- .../NamingStyle/NamingStyleCodeFixProvider.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Analyzers/Core/CodeFixes/NamingStyle/NamingStyleCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/NamingStyle/NamingStyleCodeFixProvider.cs index b2d1f25479d08..28468d36ff716 100644 --- a/src/Analyzers/Core/CodeFixes/NamingStyle/NamingStyleCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/NamingStyle/NamingStyleCodeFixProvider.cs @@ -163,12 +163,17 @@ protected override async Task> ComputeOperation #if CODE_STYLE // https://github.com/dotnet/roslyn/issues/42218 tracks removing this conditional code. return SpecializedCollections.SingletonEnumerable(codeAction); #else - var factory = _startingSolution.Services.GetRequiredService(); - return new CodeActionOperation[] + + using var _ = PooledObjects.ArrayBuilder.GetInstance(out var operations); + + operations.Add(codeAction); + var factory = _startingSolution.Services.GetService(); + if (factory is not null) { - codeAction, - factory.CreateSymbolRenamedOperation(_symbol, _newName, _startingSolution, newSolution) - }; + operations.Add(factory.CreateSymbolRenamedOperation(_symbol, _newName, _startingSolution, newSolution)); + } + + return operations.ToImmutable(); #endif } From df3a6ab083cb3f99feacdc2ebf3d9f0316768e90 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Thu, 27 Apr 2023 00:17:36 +0000 Subject: [PATCH 201/261] Merged PR 30919: Fix path to npmrc --- azure-pipelines-official.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 15123f6330571..237d6a35503be 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -150,7 +150,7 @@ stages: - task: npmAuthenticate@0 displayName: Authenticate NPM Feed inputs: - workingFile: $(Build.SourcesDirectory)/src/VisualStudio/Microsoft.CodeAnalysis.LanguageServer.Internal/.npmrc + workingFile: $(Build.SourcesDirectory)/src/VisualStudio/LanguageServer/Impl/.npmrc customEndpoint: devdiv-vs-green-npm-package-feed # Needed for SBOM tool From 5565de49dae36e68d62c1a589f12fd2431a4e487 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 27 Apr 2023 11:51:51 +1000 Subject: [PATCH 202/261] Defer initialization of the Razor components until the extension tells us that its needed --- .../RazorDynamicFileInfoProvider.cs | 23 +---- .../HostWorkspace/RazorInitializeHandler.cs | 35 ++++++++ .../RazorWorkspaceListenerInitializer.cs | 89 +++++++++++++++++++ .../Program.cs | 2 +- 4 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs index d0f87e889bf8d..b3bbd016b513d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs @@ -4,7 +4,6 @@ using System.Composition; using System.Runtime.Serialization; -using Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; @@ -18,12 +17,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; internal class RazorDynamicFileInfoProvider : IDynamicFileInfoProvider { private const string ProvideRazorDynamicFileInfoMethodName = "razor/provideDynamicFileInfo"; - private static string _projectRazorJsonFileName = "project.razor.vscode.json"; - - internal static void SetProjectRazorJsonFileName(string projectRazorJsonFileName) - { - _projectRazorJsonFileName = projectRazorJsonFileName; - } [DataContract] private class ProvideDynamicFileParams @@ -52,26 +45,18 @@ private class RemoveDynamicFileParams public event EventHandler? Updated; #pragma warning restore CS0067 - private readonly Lazy _razorWorkspaceListener; + private readonly RazorWorkspaceListenerInitializer _razorWorkspaceListenerInitializer; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RazorDynamicFileInfoProvider(Lazy workspaceFactory) + public RazorDynamicFileInfoProvider(RazorWorkspaceListenerInitializer razorWorkspaceListenerInitializer) { - _razorWorkspaceListener = new Lazy(() => - { - var razorWorkspaceListener = new RazorWorkspaceListener(); - var workspace = workspaceFactory.Value.Workspace; - razorWorkspaceListener.EnsureInitialized(workspace, _projectRazorJsonFileName); - - return razorWorkspaceListener; - }); + _razorWorkspaceListenerInitializer = razorWorkspaceListenerInitializer; } public async Task GetDynamicFileInfoAsync(ProjectId projectId, string? projectFilePath, string filePath, CancellationToken cancellationToken) { - // Make sure Razor is listening, since we have evidence of at least one .razor or .cshtml file in this workspace! - _ = _razorWorkspaceListener.Value; + _razorWorkspaceListenerInitializer.NotifyDynamicFile(projectId); var requestParams = new ProvideDynamicFileParams { RazorFiles = new[] { ProtocolConversions.GetUriFromFilePath(filePath) } }; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs new file mode 100644 index 0000000000000..cadb438da8ea6 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Composition; +using System.Runtime.Serialization; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CommonLanguageServerProtocol.Framework; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +[ExportCSharpVisualBasicStatelessLspService(typeof(RazorInitializeHandler)), Shared] +[Method("razor/initialize")] +internal class RazorInitializeHandler : ILspServiceNotificationHandler +{ + private readonly RazorWorkspaceListenerInitializer _razorWorkspaceListenerInitializer; + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public RazorInitializeHandler(RazorWorkspaceListenerInitializer razorWorkspaceListenerInitializer) + { + _razorWorkspaceListenerInitializer = razorWorkspaceListenerInitializer; + } + + public bool MutatesSolutionState => false; + public bool RequiresLSPSolution => false; + + Task INotificationHandler.HandleNotificationAsync(object request, RequestContext requestContext, CancellationToken cancellationToken) + { + _razorWorkspaceListenerInitializer.Initialize(); + + return Task.CompletedTask; + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs new file mode 100644 index 0000000000000..e69eb475938ef --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs @@ -0,0 +1,89 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; + +[Export(typeof(RazorWorkspaceListenerInitializer)), Shared] +internal sealed class RazorWorkspaceListenerInitializer +{ + private static string _projectRazorJsonFileName = "project.razor.vscode.json"; + + internal static void SetProjectRazorJsonFileName(string projectRazorJsonFileName) + { + _projectRazorJsonFileName = projectRazorJsonFileName; + } + + private readonly ILogger _logger; + private readonly Lazy _razorWorkspaceListener; + private ImmutableHashSet _projectIdWithDynamicFiles = ImmutableHashSet.Empty; + private readonly object _initializeGate = new(); + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public RazorWorkspaceListenerInitializer(Lazy workspaceFactory, ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(nameof(RazorWorkspaceListenerInitializer)); + + _razorWorkspaceListener = new Lazy(() => + { + var razorWorkspaceListener = new RazorWorkspaceListener(loggerFactory); + var workspace = workspaceFactory.Value.Workspace; + razorWorkspaceListener.EnsureInitialized(workspace, _projectRazorJsonFileName); + + return razorWorkspaceListener; + }); + } + + internal void Initialize() + { + // Only initialize once + if (_razorWorkspaceListener.IsValueCreated) + { + return; + } + + lock (_initializeGate) + { + if (_razorWorkspaceListener.IsValueCreated) + { + return; + } + + _logger.LogTrace("Initializing the Razor workspace listener"); + _ = _razorWorkspaceListener.Value; + } + + foreach (var projectId in _projectIdWithDynamicFiles) + { + _logger.LogTrace("{projectId} notifying a dynamic file for the first time", projectId); + _razorWorkspaceListener.Value.NotifyDynamicFile(projectId); + } + } + + internal void NotifyDynamicFile(ProjectId projectId) + { + if (_razorWorkspaceListener.IsValueCreated) + { + // We've been initialized, so just pass the information along + _logger.LogTrace("{projectId} forwarding on a dynamic file notification because we're initialized", projectId); + _razorWorkspaceListener.Value.NotifyDynamicFile(projectId); + return; + } + + _logger.LogTrace("{projectId} queuing up a dynamic file notify for later", projectId); + // We haven't been initialized by the extension yet, so just queue up the project for later + ImmutableInterlocked.Update(ref _projectIdWithDynamicFiles, (col, arg) => col.Add(arg), projectId); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 7b1da5f7b0986..bf6ddda993cb3 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -71,7 +71,7 @@ static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, // Allow the extension to override the razor file name to generate, in case they need to break the format if (projectRazorJsonFileName is not null) { - RazorDynamicFileInfoProvider.SetProjectRazorJsonFileName(projectRazorJsonFileName); + RazorWorkspaceListenerInitializer.SetProjectRazorJsonFileName(projectRazorJsonFileName); } // Initialize the fault handler if it's available From fc647e39f33d5bc84dcb9a4f40ca3e87c07186d7 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Fri, 28 Apr 2023 00:22:38 +0000 Subject: [PATCH 203/261] Merged PR 30816: Add publish for npm package Add publish for npm package to dotnet-tools-internal --- azure-pipelines-official.yml | 32 +++++++++++++-------- eng/publish-assets.ps1 | 2 +- src/VisualStudio/LanguageServer/Impl/.npmrc | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 237d6a35503be..42e1282adc960 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -131,28 +131,21 @@ stages: - powershell: Write-Host "##vso[task.setvariable variable=VisualStudio.DropName]Products/$(System.TeamProject)/$(Build.Repository.Name)/$(SourceBranchName)/$(Build.BuildNumber)" displayName: Setting VisualStudio.DropName variable - - task: NuGetToolInstaller@0 - inputs: - versionSpec: '4.9.2' - - task: NodeTool@0 inputs: versionSpec: '16.x' displayName: 'Install Node.js' + + - task: NuGetToolInstaller@0 + inputs: + versionSpec: '4.9.2' + # Authenticate with service connections to be able to publish packages to external nuget feeds. - task: NuGetAuthenticate@0 inputs: nuGetServiceConnections: azure-public/vs-impl, azure-public/vssdk, devdiv/engineering, devdiv/dotnet-core-internal-tooling - # Authenticates the .npmrc file for publishing to the internal AzDO feed. - # See: https://learn.microsoft.com/azure/devops/pipelines/tasks/package/npm-authenticate?view=azure-devops - - task: npmAuthenticate@0 - displayName: Authenticate NPM Feed - inputs: - workingFile: $(Build.SourcesDirectory)/src/VisualStudio/LanguageServer/Impl/.npmrc - customEndpoint: devdiv-vs-green-npm-package-feed - # Needed for SBOM tool - task: UseDotNet@2 displayName: 'Use .NET Core 3.1 runtime' @@ -328,6 +321,21 @@ stages: publishFeedCredentials: 'DevDiv - VS package feed' condition: succeeded() + # Publish language server package + - powershell: Write-Host "##vso[task.setvariable variable=NPMFileName]$((ls -file $(Build.SourcesDirectory)\artifacts\packages\Release\NPM\ | select -First 1).FullName)" + displayName: Setting NPM Package Variable + + # Authenticates the .npmrc file for publishing to the internal AzDO feed. + # See: https://learn.microsoft.com/azure/devops/pipelines/tasks/package/npm-authenticate?view=azure-devops + - task: npmAuthenticate@0 + displayName: Authenticate NPM Feed + inputs: + workingFile: $(Build.SourcesDirectory)/src/VisualStudio/LanguageServer/Impl/.npmrc + customEndpoint: devdiv-vs-green-npm-package-feed + + - script: npm publish --userconfig $(Build.SourcesDirectory)\src\VisualStudio\LanguageServer\Impl\.npmrc $(NPMFileName) + displayName: Publish Language Server NPM Package + # Publish Asset Manifests for Build Asset Registry job - task: PublishBuildArtifacts@1 displayName: Publish Asset Manifests diff --git a/eng/publish-assets.ps1 b/eng/publish-assets.ps1 index 4c5e16417c9f5..aa103ab356018 100644 --- a/eng/publish-assets.ps1 +++ b/eng/publish-assets.ps1 @@ -128,7 +128,7 @@ function Publish-Npm([string]$npmPackagesDir) { foreach ($npmPackage in Get-ChildItem -Path (Join-Path $npmPackagesDir "*") -Include *.tgz) { Write-Host "" - $publishCommandArgs = "npm publish --dryrun --userconfig ""$npmrcPath"" ""$npmPackage""" + $publishCommandArgs = "npm publish --userconfig ""$npmrcPath"" ""$npmPackage""" Write-Host "Publishing $npmPackage" $publishOutput = & cmd /c "$publishCommandArgs" if ($LastExitCode -ne 0) diff --git a/src/VisualStudio/LanguageServer/Impl/.npmrc b/src/VisualStudio/LanguageServer/Impl/.npmrc index 56a8c1610a424..816fed5f83098 100644 --- a/src/VisualStudio/LanguageServer/Impl/.npmrc +++ b/src/VisualStudio/LanguageServer/Impl/.npmrc @@ -1,3 +1,3 @@ # This must be located directly next to the package.json for compliance. -registry=https://pkgs.dev.azure.com/devdiv/DevDiv/_packaging/vs-green/npm/registry/ +registry=https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/npm/registry/ always-auth=true \ No newline at end of file From 31f979cac7b0ef976e9f953ebdc6f67776119682 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Fri, 28 Apr 2023 18:37:33 +0000 Subject: [PATCH 204/261] Merged PR 30920: Add support to ImportCompletion This is disabled by default, and no change to the filtering logic yet. Address https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1798338 Looks like this: ![image.png](https://dnceng.visualstudio.com/7ea9116e-9fac-403d-b258-b31fcf1bb293/_apis/git/repositories/7b863b8d-8cc3-431d-b06b-7136cc32bbe6/pullRequests/30920/attachments/image.png) --- ...ditorLspCompletionResultCreationService.cs | 10 +- .../AbstractLanguageServerProtocolTests.cs | 6 +- .../AbstractImportCompletionProvider.cs | 5 +- .../ImportCompletionItem.cs | 9 +- ...ractLspCompletionResultCreationService.cs} | 153 +++++++++++++++++- .../Handler/Completion/CompletionHandler.cs | 50 +++--- ...faultLspCompletionResultCreationService.cs | 47 +++--- .../ILspCompletionResultCreationService.cs | 10 +- .../Completion/LspCompletionUtilities.cs | 113 ------------- ...igurationNotificationHandler_OptionList.cs | 1 + .../Completion/CompletionFeaturesTests.cs | 101 +++++++++++- .../Completion/CompletionResolveTests.cs | 45 ++++-- .../Completion/CompletionTests.cs | 14 +- 13 files changed, 370 insertions(+), 194 deletions(-) rename src/Features/LanguageServer/Protocol/Handler/Completion/{CompletionHandler_CreateLspList.cs => AbstractLspCompletionResultCreationService.cs} (64%) delete mode 100644 src/Features/LanguageServer/Protocol/Handler/Completion/LspCompletionUtilities.cs diff --git a/src/EditorFeatures/Core/LanguageServer/EditorLspCompletionResultCreationService.cs b/src/EditorFeatures/Core/LanguageServer/EditorLspCompletionResultCreationService.cs index a9a72b8a75549..ce68681a5e31f 100644 --- a/src/EditorFeatures/Core/LanguageServer/EditorLspCompletionResultCreationService.cs +++ b/src/EditorFeatures/Core/LanguageServer/EditorLspCompletionResultCreationService.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer { [ExportWorkspaceService(typeof(ILspCompletionResultCreationService), ServiceLayer.Editor), Shared] - internal sealed class EditorLspCompletionResultCreationService : ILspCompletionResultCreationService + internal sealed class EditorLspCompletionResultCreationService : AbstractLspCompletionResultCreationService { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -28,7 +28,7 @@ public EditorLspCompletionResultCreationService() { } - public async Task CreateAsync( + protected override async Task CreateItemAndPopulateTextEditAsync( Document document, SourceText documentText, bool snippetsSupported, @@ -57,7 +57,7 @@ public EditorLspCompletionResultCreationService() } else { - await LspCompletionUtilities.PopulateSimpleTextEditAsync( + await PopulateSimpleTextEditAsync( document, documentText, itemDefaultsSupported, @@ -71,7 +71,7 @@ public EditorLspCompletionResultCreationService() return lspItem; } - public async Task ResolveAsync( + public override async Task ResolveAsync( LSP.CompletionItem lspItem, CompletionItem roslynItem, LSP.TextDocumentIdentifier textDocumentIdentifier, @@ -108,7 +108,7 @@ public EditorLspCompletionResultCreationService() Contract.ThrowIfTrue(lspItem.TextEdit != null); var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var (edit, _, _) = await LspCompletionUtilities.GenerateComplexTextEditAsync( + var (edit, _, _) = await GenerateComplexTextEditAsync( document, completionService, roslynItem, capabilityHelper.SupportSnippets, insertNewPositionPlaceholder: true, cancellationToken).ConfigureAwait(false); lspItem.TextEdit = edit; diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs index 940bea432de2b..3f4366498ef32 100644 --- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs +++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs @@ -253,7 +253,8 @@ protected static LSP.MarkupContent CreateMarkupContent(LSP.MarkupKind kind, stri string? sortText = null, string? filterText = null, long resultId = 0, - bool vsResolveTextEditOnCommit = false) + bool vsResolveTextEditOnCommit = false, + LSP.CompletionItemLabelDetails? labelDetails = null) { var position = await document.GetPositionFromLinePositionAsync( ProtocolConversions.PositionToLinePosition(request.Position), CancellationToken.None).ConfigureAwait(false); @@ -274,7 +275,8 @@ protected static LSP.MarkupContent CreateMarkupContent(LSP.MarkupKind kind, stri ResultId = resultId, }), Preselect = preselect, - VsResolveTextEditOnCommit = vsResolveTextEditOnCommit + VsResolveTextEditOnCommit = vsResolveTextEditOnCommit, + LabelDetails = labelDetails }; if (tags != null) diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs index 50c91a90be7fc..f7449a931c282 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs @@ -202,10 +202,11 @@ private static ImmutableArray GetImportedNamespaces(SyntaxContext contex async Task ShouldCompleteWithFullyQualifyTypeName() { + if (ImportCompletionItem.ShouldAlwaysAddMissingImport(completionItem)) + return false; + if (!IsAddingImportsSupported(document)) - { return true; - } // We might need to qualify unimported types to use them in an import directive, because they only affect members of the containing // import container (e.g. namespace/class/etc. declarations). diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ImportCompletionItem.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ImportCompletionItem.cs index 93c01e94aae3a..c9ac87149b582 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ImportCompletionItem.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ImportCompletionItem.cs @@ -17,14 +17,15 @@ internal static class ImportCompletionItem { // Note the additional space as prefix to the System namespace, // to make sure items from System.* get sorted ahead. - private const string OtherNamespaceSortTextFormat = "{0} {1}"; - private const string SystemNamespaceSortTextFormat = "{0} {1}"; + private const string OtherNamespaceSortTextFormat = "~{0} {1}"; + private const string SystemNamespaceSortTextFormat = "~{0} {1}"; private const string TypeAritySuffixName = nameof(TypeAritySuffixName); private const string AttributeFullName = nameof(AttributeFullName); private const string MethodKey = nameof(MethodKey); private const string ReceiverKey = nameof(ReceiverKey); private const string OverloadCountKey = nameof(OverloadCountKey); + private const string AlwaysAddMissingImportKey = nameof(AlwaysAddMissingImportKey); public static CompletionItem Create( string name, @@ -209,5 +210,9 @@ private static (ISymbol? symbol, int overloadCount) GetSymbolAndOverloadCount(Co return (compilation.GetTypeByMetadataName(fullyQualifiedName), 0); } + + public static CompletionItem MarkItemToAlwaysAddMissingImport(CompletionItem item) => item.WithProperties(item.Properties.Add(AlwaysAddMissingImportKey, AlwaysAddMissingImportKey)); + + public static bool ShouldAlwaysAddMissingImport(CompletionItem item) => item.Properties.ContainsKey(AlwaysAddMissingImportKey); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler_CreateLspList.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/AbstractLspCompletionResultCreationService.cs similarity index 64% rename from src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler_CreateLspList.cs rename to src/Features/LanguageServer/Protocol/Handler/Completion/AbstractLspCompletionResultCreationService.cs index 194a6c65a3b36..4b065f413e7e9 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler_CreateLspList.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Completion/AbstractLspCompletionResultCreationService.cs @@ -5,22 +5,29 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion; -using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; +using Microsoft.CodeAnalysis.Completion.Providers; +using Microsoft.CodeAnalysis.Completion.Providers.Snippets; +using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; -namespace Microsoft.CodeAnalysis.LanguageServer.Handler +namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion { - internal sealed partial class CompletionHandler + internal abstract class AbstractLspCompletionResultCreationService : ILspCompletionResultCreationService { - private static async Task ConvertToLspCompletionListAsync( + protected abstract Task CreateItemAndPopulateTextEditAsync(Document document, SourceText documentText, bool snippetsSupported, bool itemDefaultsSupported, TextSpan defaultSpan, CompletionItem item, CompletionService completionService, CancellationToken cancellationToken); + public abstract Task ResolveAsync(LSP.CompletionItem lspItem, CompletionItem roslynItem, LSP.TextDocumentIdentifier textDocumentIdentifier, Document document, CompletionCapabilityHelper capabilityHelper, CompletionService completionService, CompletionOptions completionOptions, SymbolDescriptionOptions symbolDescriptionOptions, CancellationToken cancellationToken); + + public async Task ConvertToLspCompletionListAsync( Document document, CompletionCapabilityHelper capabilityHelper, CompletionList list, bool isIncomplete, long resultId, @@ -90,9 +97,12 @@ async Task CreateLSPCompletionItemAsync(CompletionItem item) { // Defer to host to create the actual completion item (including potential subclasses), and add any // custom information. - var lspItem = await creationService.CreateAsync( + var lspItem = await CreateItemAndPopulateTextEditAsync( document, documentText, capabilityHelper.SupportSnippets, defaultEditRangeSupported, defaultSpan, item, completionService, cancellationToken).ConfigureAwait(false); + if (!item.InlineDescription.IsEmpty()) + lspItem.LabelDetails = new() { Description = item.InlineDescription }; + // Now add data common to all hosts. lspItem.Data = completionItemResolveData; @@ -103,7 +113,7 @@ async Task CreateLSPCompletionItemAsync(CompletionItem item) lspItem.FilterText = item.FilterText; lspItem.Kind = GetCompletionKind(item.Tags, capabilityHelper.SupportedItemKinds); - lspItem.Preselect = ShouldItemBePreselected(item); + lspItem.Preselect = CompletionHandler.ShouldItemBePreselected(item); lspItem.CommitCharacters = GetCommitCharacters(item, commitCharactersRuleCache, lspVSClientCapability); @@ -287,5 +297,136 @@ public int GetHashCode([DisallowNull] ImmutableArray GenerateAdditionalTextEditForImportCompletionAsync( + CompletionItem selectedItem, + Document document, + CompletionService completionService, + CancellationToken cancellationToken) + { + Debug.Assert(selectedItem.Flags.IsExpanded()); + selectedItem = ImportCompletionItem.MarkItemToAlwaysAddMissingImport(selectedItem); + var completionChange = await completionService.GetChangeAsync(document, selectedItem, cancellationToken: cancellationToken).ConfigureAwait(false); + + var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + using var _ = ArrayBuilder.GetInstance(out var builder); + foreach (var change in completionChange.TextChanges) + { + if (change.NewText == selectedItem.DisplayText) + continue; + + builder.Add(new LSP.TextEdit() + { + NewText = change.NewText!, + Range = ProtocolConversions.TextSpanToRange(change.Span, sourceText), + }); + } + + return builder.ToArray(); + } + + public static async Task<(LSP.TextEdit edit, bool isSnippetString, int? newPosition)> GenerateComplexTextEditAsync( + Document document, + CompletionService completionService, + CompletionItem selectedItem, + bool snippetsSupported, + bool insertNewPositionPlaceholder, + CancellationToken cancellationToken) + { + Debug.Assert(selectedItem.IsComplexTextEdit); + + var completionChange = await completionService.GetChangeAsync(document, selectedItem, cancellationToken: cancellationToken).ConfigureAwait(false); + var completionChangeSpan = completionChange.TextChange.Span; + var newText = completionChange.TextChange.NewText; + Contract.ThrowIfNull(newText); + + var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var textEdit = new LSP.TextEdit() + { + NewText = newText, + Range = ProtocolConversions.TextSpanToRange(completionChangeSpan, documentText), + }; + + var isSnippetString = false; + var newPosition = completionChange.NewPosition; + + if (snippetsSupported) + { + if (SnippetCompletionItem.IsSnippet(selectedItem) + && completionChange.Properties.TryGetValue(SnippetCompletionItem.LSPSnippetKey, out var lspSnippetChangeText)) + { + textEdit.NewText = lspSnippetChangeText; + isSnippetString = true; + newPosition = null; + } + else if (insertNewPositionPlaceholder) + { + var caretPosition = completionChange.NewPosition; + if (caretPosition.HasValue) + { + // caretPosition is the absolute position of the caret in the document. + // We want the position relative to the start of the snippet. + var relativeCaretPosition = caretPosition.Value - completionChangeSpan.Start; + + // The caret could technically be placed outside the bounds of the text + // being inserted. This situation is currently unsupported in LSP, so in + // these cases we won't move the caret. + if (relativeCaretPosition >= 0 && relativeCaretPosition <= newText.Length) + { + textEdit.NewText = textEdit.NewText.Insert(relativeCaretPosition, "$0"); + } + } + } + } + + return (textEdit, isSnippetString, newPosition); + } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs index 46d9e5b137581..f6b8284669a02 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Completion/CompletionHandler.cs @@ -3,14 +3,12 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion; -using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; using Microsoft.CodeAnalysis.Options; @@ -36,7 +34,8 @@ internal sealed partial class CompletionHandler : ILspServiceDocumentRequestHand [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CompletionHandler(IGlobalOptionService globalOptions) + public CompletionHandler( + IGlobalOptionService globalOptions) { _globalOptions = globalOptions; } @@ -70,7 +69,9 @@ public CompletionHandler(IGlobalOptionService globalOptions) return null; var (list, isIncomplete, resultId) = completionListResult.Value; - return await ConvertToLspCompletionListAsync(document, capabilityHelper, list, isIncomplete, resultId, cancellationToken) + + var creationService = document.Project.Solution.Services.GetRequiredService(); + return await creationService.ConvertToLspCompletionListAsync(document, capabilityHelper, list, isIncomplete, resultId, cancellationToken) .ConfigureAwait(false); } @@ -218,32 +219,37 @@ public static bool ShouldItemBePreselected(CompletionItem completionItem) private CompletionOptions GetCompletionOptions(Document document, CompletionCapabilityHelper capabilityHelper) { - // Filter out unimported types for now as there are two issues with providing them: - // 1. LSP client does not currently provide a way to provide detail text on the completion item to show the namespace. - // https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1076759 - // 2. We need to figure out how to provide the text edits along with the completion item or provide them in the resolve request. - // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/985860/ - // 3. LSP client should support completion filters / expanders - // - // Also don't trigger completion in argument list automatically, since LSP currently has no concept of soft selection. - // We want to avoid committing selected item with commit chars like `"` and `)`. - var option = _globalOptions.GetCompletionOptions(document.Project.Language) with - { - ShowItemsFromUnimportedNamespaces = false, - ExpandedCompletionBehavior = ExpandedCompletionMode.NonExpandedItemsOnly, - UpdateImportCompletionCacheInBackground = false, - }; + var options = _globalOptions.GetCompletionOptions(document.Project.Language); - if (!capabilityHelper.SupportVSInternalClientCapabilities) + if (capabilityHelper.SupportVSInternalClientCapabilities) + { + // Filter out unimported types for now as there are two issues with providing them: + // 1. LSP client does not currently provide a way to provide detail text on the completion item to show the namespace. + // https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1076759 + // 2. We need to figure out how to provide the text edits along with the completion item or provide them in the resolve request. + // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/985860/ + // 3. LSP client should support completion filters / expanders + options = options with + { + ShowItemsFromUnimportedNamespaces = false, + ExpandedCompletionBehavior = ExpandedCompletionMode.NonExpandedItemsOnly, + UpdateImportCompletionCacheInBackground = false, + }; + } + else { - option = option with + var updateImportCompletionCacheInBackground = options.ShowItemsFromUnimportedNamespaces is true; + options = options with { + // Don't trigger completion in argument list automatically, since LSP currently has no concept of soft selection. + // We want to avoid committing selected item with commit chars like `"` and `)`. TriggerInArgumentLists = false, ShowNewSnippetExperienceUserOption = false, + UpdateImportCompletionCacheInBackground = updateImportCompletionCacheInBackground }; } - return option; + return options; } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/DefaultLspCompletionResultCreationService.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/DefaultLspCompletionResultCreationService.cs index 84ce7ef538bd7..ab02cb3e0a6f0 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Completion/DefaultLspCompletionResultCreationService.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Completion/DefaultLspCompletionResultCreationService.cs @@ -10,12 +10,13 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion { [ExportWorkspaceService(typeof(ILspCompletionResultCreationService), ServiceLayer.Default), Shared] - internal sealed class DefaultLspCompletionResultCreationService : ILspCompletionResultCreationService + internal sealed class DefaultLspCompletionResultCreationService : AbstractLspCompletionResultCreationService { /// /// Command name implemented by the client and invoked when an item with complex edit is committed. @@ -28,7 +29,7 @@ public DefaultLspCompletionResultCreationService() { } - public async Task CreateAsync(Document document, + protected override async Task CreateItemAndPopulateTextEditAsync(Document document, SourceText documentText, bool snippetsSupported, bool itemDefaultsSupported, @@ -42,16 +43,13 @@ public DefaultLspCompletionResultCreationService() if (item.IsComplexTextEdit) { // For complex change, we'd insert a placeholder edit as part of completion - // and rely on a post resolution command to make the actual change. - lspItem.TextEdit = new LSP.TextEdit() - { - NewText = item.DisplayText[..Math.Min(defaultSpan.Length, item.DisplayText.Length)], - Range = ProtocolConversions.TextSpanToRange(defaultSpan, documentText), - }; + // and rely on resolve request and a post resolution command to make the full change. + var completionChange = CompletionChange.Create(new TextChange(defaultSpan, item.DisplayText)); + PopulateTextEdit(lspItem, completionChange, documentText, itemDefaultsSupported, defaultSpan); } else { - await LspCompletionUtilities.PopulateSimpleTextEditAsync( + await PopulateSimpleTextEditAsync( document, documentText, itemDefaultsSupported, @@ -65,7 +63,7 @@ public DefaultLspCompletionResultCreationService() return lspItem; } - public async Task ResolveAsync( + public override async Task ResolveAsync( LSP.CompletionItem lspItem, CompletionItem roslynItem, LSP.TextDocumentIdentifier textDocumentIdentifier, @@ -84,19 +82,30 @@ public DefaultLspCompletionResultCreationService() if (roslynItem.IsComplexTextEdit) { - var (textEdit, isSnippetString, newPosition) = await LspCompletionUtilities.GenerateComplexTextEditAsync( - document, completionService, roslynItem, capabilityHelper.SupportSnippets, insertNewPositionPlaceholder: false, cancellationToken).ConfigureAwait(false); + if (roslynItem.Flags.IsExpanded()) + { + var additionalEdits = await GenerateAdditionalTextEditForImportCompletionAsync(roslynItem, document, completionService, cancellationToken).ConfigureAwait(false); + lspItem.AdditionalTextEdits = additionalEdits; + } + else + { + var (textEdit, isSnippetString, newPosition) = await GenerateComplexTextEditAsync( + document, completionService, roslynItem, capabilityHelper.SupportSnippets, insertNewPositionPlaceholder: false, cancellationToken).ConfigureAwait(false); - var lspOffset = newPosition is null ? -1 : newPosition.Value; + var lspOffset = newPosition is null ? -1 : newPosition.Value; - lspItem.Command = new LSP.Command() - { - CommandIdentifier = CompleteComplexEditCommand, - Title = nameof(CompleteComplexEditCommand), - Arguments = new object[] { textDocumentIdentifier.Uri, textEdit, isSnippetString, lspOffset } - }; + lspItem.Command = new LSP.Command() + { + CommandIdentifier = CompleteComplexEditCommand, + Title = nameof(CompleteComplexEditCommand), + Arguments = new object[] { textDocumentIdentifier.Uri, textEdit, isSnippetString, lspOffset } + }; + } } + if (!roslynItem.InlineDescription.IsEmpty()) + lspItem.LabelDetails = new() { Description = roslynItem.InlineDescription }; + return lspItem; } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/ILspCompletionResultCreationService.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/ILspCompletionResultCreationService.cs index 41b3f29f39bd7..7bbfca2cca8d2 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Completion/ILspCompletionResultCreationService.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Completion/ILspCompletionResultCreationService.cs @@ -14,14 +14,10 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion { internal interface ILspCompletionResultCreationService : IWorkspaceService { - Task CreateAsync( + Task ConvertToLspCompletionListAsync( Document document, - SourceText documentText, - bool snippetsSupported, - bool itemDefaultsSupported, - TextSpan defaultSpan, - CompletionItem item, - CompletionService completionService, + CompletionCapabilityHelper capabilityHelper, + CompletionList list, bool isIncomplete, long resultId, CancellationToken cancellationToken); Task ResolveAsync( diff --git a/src/Features/LanguageServer/Protocol/Handler/Completion/LspCompletionUtilities.cs b/src/Features/LanguageServer/Protocol/Handler/Completion/LspCompletionUtilities.cs deleted file mode 100644 index 64cbce9d5202a..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/Completion/LspCompletionUtilities.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Completion; -using Microsoft.CodeAnalysis.Completion.Providers.Snippets; -using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; -using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Completion -{ - internal static class LspCompletionUtilities - { - public static async Task PopulateSimpleTextEditAsync( - Document document, - SourceText documentText, - bool itemDefaultsSupported, - TextSpan defaultSpan, - CompletionItem item, - LSP.CompletionItem lspItem, - CompletionService completionService, - CancellationToken cancellationToken) - { - Contract.ThrowIfTrue(item.IsComplexTextEdit); - Contract.ThrowIfNull(lspItem.Label); - - var completionChange = await completionService.GetChangeAsync(document, item, cancellationToken: cancellationToken).ConfigureAwait(false); - var completionChangeSpan = completionChange.TextChange.Span; - var newText = completionChange.TextChange.NewText ?? string.Empty; - - // If the change's span is different from default, then the item should be mark as IsComplexTextEdit. - // But since we don't have a way to enforce this, we'll just check for it here. - Debug.Assert(completionChangeSpan == defaultSpan); - - if (itemDefaultsSupported && completionChangeSpan == defaultSpan) - { - // We only need to store the new text as the text edit text when it differs from Label. - if (!lspItem.Label.Equals(newText, StringComparison.Ordinal)) - lspItem.TextEditText = newText; - } - else - { - lspItem.TextEdit = new LSP.TextEdit() - { - NewText = newText, - Range = ProtocolConversions.TextSpanToRange(completionChangeSpan, documentText), - }; - } - } - - public static async Task<(LSP.TextEdit edit, bool isSnippetString, int? newPosition)> GenerateComplexTextEditAsync( - Document document, - CompletionService completionService, - CompletionItem selectedItem, - bool snippetsSupported, - bool insertNewPositionPlaceholder, - CancellationToken cancellationToken) - { - Debug.Assert(selectedItem.IsComplexTextEdit); - - var completionChange = await completionService.GetChangeAsync(document, selectedItem, cancellationToken: cancellationToken).ConfigureAwait(false); - var completionChangeSpan = completionChange.TextChange.Span; - var newText = completionChange.TextChange.NewText; - Contract.ThrowIfNull(newText); - - var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var textEdit = new LSP.TextEdit() - { - NewText = newText, - Range = ProtocolConversions.TextSpanToRange(completionChangeSpan, documentText), - }; - - var isSnippetString = false; - var newPosition = completionChange.NewPosition; - - if (snippetsSupported) - { - if (SnippetCompletionItem.IsSnippet(selectedItem) - && completionChange.Properties.TryGetValue(SnippetCompletionItem.LSPSnippetKey, out var lspSnippetChangeText)) - { - textEdit.NewText = lspSnippetChangeText; - isSnippetString = true; - newPosition = null; - } - else if (insertNewPositionPlaceholder) - { - var caretPosition = completionChange.NewPosition; - if (caretPosition.HasValue) - { - // caretPosition is the absolute position of the caret in the document. - // We want the position relative to the start of the snippet. - var relativeCaretPosition = caretPosition.Value - completionChangeSpan.Start; - - // The caret could technically be placed outside the bounds of the text - // being inserted. This situation is currently unsupported in LSP, so in - // these cases we won't move the caret. - if (relativeCaretPosition >= 0 && relativeCaretPosition <= newText.Length) - { - textEdit.NewText = textEdit.NewText.Insert(relativeCaretPosition, "$0"); - } - } - } - } - - return (textEdit, isSnippetString, newPosition); - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs b/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs index eb7b9fdb87254..646690539eaba 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Configuration/DidChangeConfigurationNotificationHandler_OptionList.cs @@ -28,6 +28,7 @@ internal partial class DidChangeConfigurationNotificationHandler CompletionOptionsStorage.ShowNameSuggestions, CompletionOptionsStorage.ShowItemsFromUnimportedNamespaces, CompletionOptionsStorage.ProvideRegexCompletions, + CompletionOptionsStorage.ShowItemsFromUnimportedNamespaces, QuickInfoOptionsStorage.ShowRemarksInQuickInfo, // Go to definition MetadataAsSourceOptionsStorage.NavigateToDecompiledSources, diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs index d0df77fe81c9b..249499c5fb531 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs @@ -2,14 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Editor.UnitTests; +using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; @@ -20,7 +25,7 @@ public class CompletionFeaturesTests : AbstractLanguageServerProtocolTests { protected override TestComposition Composition => FeaturesLspComposition; - public CompletionFeaturesTests(ITestOutputHelper? testOutputHelper) : base(testOutputHelper) + public CompletionFeaturesTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } @@ -57,4 +62,98 @@ public int M() AssertEx.NotNull(results); Assert.NotEmpty(results.Items); } + + [Theory, CombinatorialData] + public async Task TestImportCompletion(bool mutatingLspWorkspace) + { + var clientCapabilities = new LSP.ClientCapabilities + { + TextDocument = new LSP.TextDocumentClientCapabilities + { + Completion = new LSP.CompletionSetting + { + CompletionItem = new LSP.CompletionItemSetting + { + CommitCharactersSupport = true, + LabelDetailsSupport = true, + ResolveSupport = new LSP.ResolveSupportSetting + { + Properties = new string[] { "documentation", "additionalTextEdits", "command", "labelDetail" } + } + }, + + CompletionListSetting = new LSP.CompletionListSetting + { + ItemDefaults = new string[] { CompletionCapabilityHelper.EditRangePropertyName, CompletionCapabilityHelper.DataPropertyName, CompletionCapabilityHelper.CommitCharactersPropertyName } + }, + }, + } + }; + + var markup = +@" +class A +{ + void M() + { + Task{|caret:|} + } +}"; + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, clientCapabilities); + var completionParams = CreateCompletionParams( + testLspServer.GetLocations("caret").Single(), + invokeKind: LSP.VSInternalCompletionInvokeKind.Explicit, + triggerCharacter: "\0", + triggerKind: LSP.CompletionTriggerKind.Invoked); + + // Make sure the unimported types option is on by default. + testLspServer.TestWorkspace.GlobalOptions.SetGlobalOption(CompletionOptionsStorage.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, true); + testLspServer.TestWorkspace.GlobalOptions.SetGlobalOption(CompletionOptionsStorage.ForceExpandedCompletionIndexCreation, true); + + var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); + + var completionResult = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCompletionName, completionParams, CancellationToken.None).ConfigureAwait(false); + Assert.NotNull(completionResult.ItemDefaults.EditRange); + Assert.NotNull(completionResult.ItemDefaults.Data); + Assert.NotNull(completionResult.ItemDefaults.CommitCharacters); + + var actualItem = completionResult.Items.First(i => i.Label == "Task"); + Assert.Equal("System.Threading.Tasks", actualItem.LabelDetails.Description); + Assert.Equal("~Task System.Threading.Tasks", actualItem.SortText); + Assert.Equal(CompletionItemKind.Class, actualItem.Kind); + Assert.Null(actualItem.LabelDetails.Detail); + Assert.Null(actualItem.FilterText); + Assert.Null(actualItem.TextEdit); + Assert.Null(actualItem.TextEditText); + Assert.Null(actualItem.AdditionalTextEdits); + Assert.Null(actualItem.Command); + Assert.Null(actualItem.CommitCharacters); + Assert.Null(actualItem.Data); + Assert.Null(actualItem.Detail); + Assert.Null(actualItem.Documentation); + + actualItem.Data = completionResult.ItemDefaults.Data; + + var resolvedItem = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentCompletionResolveName, actualItem, CancellationToken.None).ConfigureAwait(false); + Assert.Equal("System.Threading.Tasks", resolvedItem.LabelDetails.Description); + Assert.Equal("~Task System.Threading.Tasks", resolvedItem.SortText); + Assert.Equal(CompletionItemKind.Class, resolvedItem.Kind); + + var expectedAdditionalEdit = new TextEdit() { NewText = "using System.Threading.Tasks;\r\n\r\n", Range = new() { Start = new(1, 0), End = new(1, 0) } }; + AssertJsonEquals(new[] { expectedAdditionalEdit }, resolvedItem.AdditionalTextEdits); + + Assert.Null(resolvedItem.LabelDetails.Detail); + Assert.Null(resolvedItem.FilterText); + Assert.Null(resolvedItem.TextEdit); + Assert.Null(resolvedItem.TextEditText); + Assert.Null(resolvedItem.Command); + Assert.Null(resolvedItem.Detail); + + var expectedDocumentation = new MarkupContent() + { + Kind = LSP.MarkupKind.PlainText, + Value = "(awaitable) class System.Threading.Tasks.Task" + }; + AssertJsonEquals(resolvedItem.Documentation, expectedDocumentation); + } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs index 7a18f61c044b8..a2a7fa539ddf7 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionResolveTests.cs @@ -64,7 +64,7 @@ void M() label: "A").ConfigureAwait(false); var description = new ClassifiedTextElement(CreateClassifiedTextRunForClass("A")); - var expected = CreateResolvedCompletionItem(clientCompletionItem, description, "class A", null); + var expected = CreateResolvedCompletionItem(clientCompletionItem, description, null); var results = (LSP.VSInternalCompletionItem)await RunResolveCompletionItemAsync( testLspServer, clientCompletionItem).ConfigureAwait(false); @@ -86,7 +86,7 @@ void M() var clientCompletionItem = await GetCompletionItemToResolveAsync(testLspServer, label: "A").ConfigureAwait(false); var description = new ClassifiedTextElement(CreateClassifiedTextRunForClass("A")); - var expected = CreateResolvedCompletionItem(clientCompletionItem, description, "class A", null); + var expected = CreateResolvedCompletionItem(clientCompletionItem, description, null); var results = (LSP.VSInternalCompletionItem)await RunResolveCompletionItemAsync( testLspServer, clientCompletionItem).ConfigureAwait(false); @@ -182,7 +182,7 @@ class B : A var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var selectedItem = CodeAnalysis.Completion.CompletionItem.Create(displayText: "M", isComplexTextEdit: true); - var (textEdit, _, _) = await LspCompletionUtilities.GenerateComplexTextEditAsync( + var (textEdit, _, _) = await AbstractLspCompletionResultCreationService.GenerateComplexTextEditAsync( document, new TestCaretOutOfScopeCompletionService(testLspServer.TestWorkspace.Services.SolutionServices), selectedItem, snippetsSupported: true, insertNewPositionPlaceholder: true, CancellationToken.None).ConfigureAwait(false); Assert.Equal(@"public override void M() @@ -352,24 +352,51 @@ private static async Task RunResolveCompletionItemAsync(Test completionItem, CancellationToken.None); } - private static LSP.VSInternalCompletionItem CreateResolvedCompletionItem( + private static VSInternalCompletionItem Clone(VSInternalCompletionItem completionItem) + { + return new VSInternalCompletionItem() + { + Label = completionItem.Label, + LabelDetails = completionItem.LabelDetails, + Kind = completionItem.Kind, + Detail = completionItem.Detail, + Documentation = completionItem.Documentation, + Preselect = completionItem.Preselect, + SortText = completionItem.SortText, + FilterText = completionItem.FilterText, + InsertText = completionItem.InsertText, + InsertTextFormat = completionItem.InsertTextFormat, + TextEdit = completionItem.TextEdit, + TextEditText = completionItem.TextEditText, + AdditionalTextEdits = completionItem.AdditionalTextEdits, + CommitCharacters = completionItem.CommitCharacters, + Command = completionItem.Command, + Data = completionItem.Data, + Icon = completionItem.Icon, + Description = completionItem.Description, + VsCommitCharacters = completionItem.VsCommitCharacters, + VsResolveTextEditOnCommit = completionItem.VsResolveTextEditOnCommit, + }; + } + + private static VSInternalCompletionItem CreateResolvedCompletionItem( VSInternalCompletionItem completionItem, ClassifiedTextElement description, - string detail, string documentation) { - completionItem.Detail = detail; + var expectedCompletionItem = Clone(completionItem); + if (documentation != null) { - completionItem.Documentation = new LSP.MarkupContent() + expectedCompletionItem.Documentation = new MarkupContent() { Kind = LSP.MarkupKind.PlainText, Value = documentation }; } - completionItem.Description = description; - return completionItem; + expectedCompletionItem.Description = description; + return expectedCompletionItem; } private static ClassifiedTextRun[] CreateClassifiedTextRunForClass(string className) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs index 35e84560b11ff..df61c36cb3f7a 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs @@ -291,8 +291,9 @@ void M() await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, s_vsCompletionCapabilities); var solution = testLspServer.TestWorkspace.CurrentSolution; - // Make sure the unimported types option is on by default. + // Make sure the unimported types option is on testLspServer.TestWorkspace.GlobalOptions.SetGlobalOption(CompletionOptionsStorage.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, true); + testLspServer.TestWorkspace.GlobalOptions.SetGlobalOption(CompletionOptionsStorage.ForceExpandedCompletionIndexCreation, true); var completionParams = CreateCompletionParams( testLspServer.GetLocations("caret").Single(), @@ -406,7 +407,8 @@ void M() var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var expected = await CreateCompletionItemAsync( - label: "d", kind: LSP.CompletionItemKind.Text, tags: new string[] { "Text" }, request: completionParams, document: document, sortText: "0000").ConfigureAwait(false); + label: "d", kind: LSP.CompletionItemKind.Text, tags: new string[] { "Text" }, request: completionParams, document: document, sortText: "0000", + labelDetails: new() { Description = "shortdate" }).ConfigureAwait(false); var results = await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); AssertJsonEquals(expected, results.Items.First()); @@ -467,7 +469,7 @@ void M() var expected = await CreateCompletionItemAsync( label: @"\A", kind: LSP.CompletionItemKind.Text, tags: new string[] { "Text" }, request: completionParams, document: document, textEditText: @"\\A", - sortText: "0000").ConfigureAwait(false); + sortText: "0000", labelDetails: new() { Description = "startofstringonly" }).ConfigureAwait(false); var results = await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); AssertJsonEquals(expected, results.Items.First()); @@ -504,7 +506,7 @@ void M() var expected = await CreateCompletionItemAsync( label: @"\A", kind: LSP.CompletionItemKind.Text, tags: new string[] { "Text" }, request: completionParams, document: document, - sortText: "0000", vsResolveTextEditOnCommit: true).ConfigureAwait(false); + sortText: "0000", vsResolveTextEditOnCommit: true, labelDetails: new() { Description = "startofstringonly" }).ConfigureAwait(false); var results = await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); AssertJsonEquals(expected, results.Items.First()); @@ -541,7 +543,7 @@ void M() var expected = await CreateCompletionItemAsync( label: @"\A", kind: LSP.CompletionItemKind.Text, tags: new string[] { "Text" }, request: completionParams, document: document, - sortText: "0000", vsResolveTextEditOnCommit: true).ConfigureAwait(false); + sortText: "0000", vsResolveTextEditOnCommit: true, labelDetails: new() { Description = "startofstringonly" }).ConfigureAwait(false); var results = await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); AssertJsonEquals(expected, results.Items.First()); @@ -589,7 +591,7 @@ void M() var expected = await CreateCompletionItemAsync( label: @"\A", kind: LSP.CompletionItemKind.Text, tags: new string[] { "Text" }, request: completionParams, document: document, textEdit: textEdit, - sortText: "0000").ConfigureAwait(false); + sortText: "0000", labelDetails: new() { Description = "startofstringonly" }).ConfigureAwait(false); var results = await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); AssertJsonEquals(expected, results.Items.First()); From c548c5c3bb2ca23e4134ac70189f8569a405ace5 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 1 May 2023 07:44:20 +1000 Subject: [PATCH 205/261] Bump Razor --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 87fa3a544a96a..82646727a2bd3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -78,7 +78,7 @@ $(RefOnlyMicrosoftBuildPackagesVersion) 6.0.0-preview.0.15 17.2.31 - 7.0.0-preview.23220.3 + 7.0.0-preview.23229.1 + + + @@ -35,6 +44,8 @@ + + From 303bf4e113add66cfc6cec21e17ad0a34af52c34 Mon Sep 17 00:00:00 2001 From: tmat Date: Fri, 28 Apr 2023 17:55:01 -0700 Subject: [PATCH 213/261] Include LanguageServer.Internal in MEF composition --- eng/targets/Imports.targets | 3 +- .../Contracts/ITelemetryReporter.cs | 16 ++ .../ExportProviderBuilder.cs | 30 ++- .../Logging/RoslynLogger.cs | 28 +-- ...crosoft.CodeAnalysis.LanguageServer.csproj | 7 +- .../Program.cs | 24 ++- .../Services/Telemetry/TelemetryService.cs | 80 -------- .../Impl/Logging/VSCodeTelemetryLogger.cs | 182 ++++++++++++++++++ ...isualStudio.LanguageServices.DevKit.csproj | 11 ++ .../DevKit/Impl/VSCodeTelemetryLogger.cs | 32 +-- 10 files changed, 291 insertions(+), 122 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs delete mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs create mode 100644 src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index 53eca693cbd1e..89edf03b67cd2 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -257,10 +257,11 @@ <_InternalsVisibleToAttribute Include="System.Runtime.CompilerServices.RestrictedInternalsVisibleToAttribute"> <_Parameter1>%(RestrictedInternalsVisibleTo.Identity) <_Parameter2 Condition="'%(RestrictedInternalsVisibleTo.Partner)' != ''">Microsoft.CodeAnalysis.ExternalAccess.%(RestrictedInternalsVisibleTo.Partner).Api + <_Parameter2 Condition="'%(RestrictedInternalsVisibleTo.Namespace)' != ''">%(RestrictedInternalsVisibleTo.Namespace) - + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs new file mode 100644 index 0000000000000..59c3e818563ec --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Contracts.Telemetry; + +internal interface ITelemetryReporter +{ + void InitializeSession(string telemetryLevel); + void Log(string name, ImmutableDictionary properties); + void LogBlockStart(string eventName, int kind, int blockId); + void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken); + void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception); +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index a0ecbc0478ec3..29703b1e53254 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Runtime.Loader; using Microsoft.CodeAnalysis.LanguageServer.Logging; +using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -13,22 +14,24 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal sealed class ExportProviderBuilder { - public static async Task CreateExportProviderAsync() + private const string AddonsAssemblyFileName = "Microsoft.CodeAnalysis.LanguageServer.Internal.dll"; + + public static async Task CreateExportProviderAsync(string? addonsDirectory) { var baseDirectory = AppContext.BaseDirectory; var resolver = new Resolver(new CustomExportAssemblyLoader(baseDirectory)); // Load any Roslyn assemblies from the extension directory - var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll"); - assembliesToDiscover = assembliesToDiscover.Concat(Directory.EnumerateFiles(baseDirectory, "Microsoft.ServiceHub*.dll")); + var assemblyPaths = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll"); + assemblyPaths = assemblyPaths.Concat(Directory.EnumerateFiles(baseDirectory, "Microsoft.ServiceHub*.dll")); // Temporarily explicitly load the dlls we want to add to the MEF composition. This is due to a runtime bug // in the 7.0.4 runtime where the APIs MEF uses to load assemblies break with R2R assemblies. // See https://github.com/dotnet/runtime/issues/83526 // // Once a newer version of the runtime is widely available, we can remove this. - foreach (var path in assembliesToDiscover) + foreach (var path in assemblyPaths) { Assembly.LoadFrom(path); } @@ -38,10 +41,25 @@ public static async Task CreateExportProviderAsync() new AttributedPartDiscovery(resolver, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) new AttributedPartDiscoveryV1(resolver)); + var assemblies = new List() + { + typeof(ExportProviderBuilder).Assembly + }; + + // Additional Roslyn services: + if (addonsDirectory != null) + { + var loadContext = AssemblyLoadContextWrapper.TryCreate(name: "CodeAnalysisAddons", addonsDirectory, logger: null); + if (loadContext != null) + { + assemblies.Add(loadContext.GetAssembly(AddonsAssemblyFileName)); + } + } + // TODO - we should likely cache the catalog so we don't have to rebuild it every time. var catalog = ComposableCatalog.Create(resolver) - .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly())) - .AddParts(await discovery.CreatePartsAsync(assembliesToDiscover)) + .AddParts(await discovery.CreatePartsAsync(assemblies)) + .AddParts(await discovery.CreatePartsAsync(assemblyPaths)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import // Assemble the parts into a valid graph. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs index a1f1286e0fa6c..e41677f5873f6 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs @@ -7,13 +7,12 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Contracts.Telemetry; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Logging @@ -25,22 +24,23 @@ internal class RoslynLogger : ILogger private static readonly ConcurrentDictionary<(FunctionId id, string name), string> s_propertyMap = new(); private readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); - private static TelemetryService? _telemetryService; + private static ITelemetryReporter? _telemetryReporter; private RoslynLogger() { } - public static void Initialize(string? telemetryLevel, string? location) + public static void Initialize(ITelemetryReporter? reporter, string? telemetryLevel) { - Roslyn.Utilities.Contract.ThrowIfTrue(_instance is not null); + Contract.ThrowIfTrue(_instance is not null); - FatalError.Handler = (exception, severity, forceDump) => ReportFault(exception, severity, forceDump); + FatalError.Handler = ReportFault; FatalError.CopyHandlerTo(typeof(Compilation).Assembly); - if (telemetryLevel is not null && location is not null) + if (reporter is not null && telemetryLevel is not null) { - _telemetryService = TelemetryService.TryCreate(telemetryLevel, location); + reporter.InitializeSession(telemetryLevel); + _telemetryReporter = reporter; } _instance = new(); @@ -75,12 +75,12 @@ private static void ReportFault(Exception exception, ErrorSeverity severity, boo return; } - if (_telemetryService is not null) + if (_telemetryReporter is not null) { var eventName = GetEventName(FunctionId.NonFatalWatson); var description = GetDescription(exception); var currentProcess = Process.GetCurrentProcess(); - _telemetryService.ReportFault(eventName, description, (int)severity, forceDump, currentProcess.Id, exception); + _telemetryReporter.ReportFault(eventName, description, (int)severity, forceDump, currentProcess.Id, exception); } } catch (OutOfMemoryException) @@ -94,7 +94,7 @@ private static void ReportFault(Exception exception, ErrorSeverity severity, boo } public bool IsEnabled(FunctionId functionId) - => _telemetryService is not null; + => _telemetryReporter is not null; public void Log(FunctionId functionId, LogMessage logMessage) { @@ -103,7 +103,7 @@ public void Log(FunctionId functionId, LogMessage logMessage) try { - _telemetryService?.Log(name, properties); + _telemetryReporter?.Log(name, properties); } catch { @@ -117,7 +117,7 @@ public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int bloc try { - _telemetryService?.LogBlockStart(eventName, (int)kind, blockId); + _telemetryReporter?.LogBlockStart(eventName, (int)kind, blockId); } catch { @@ -129,7 +129,7 @@ public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int blockI var properties = GetProperties(functionId, logMessage, delta); try { - _telemetryService?.LogBlockEnd(blockId, properties, cancellationToken); + _telemetryReporter?.LogBlockEnd(blockId, properties, cancellationToken); } catch { diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 8a4e3796ef6bd..3b00d3496de14 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -66,7 +66,12 @@ - + + + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 7b1da5f7b0986..eee376e5ee225 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -8,6 +8,7 @@ using System.CommandLine.Parsing; using System.Diagnostics; using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Contracts.Telemetry; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services.HelloWorld; @@ -23,7 +24,15 @@ var parser = CreateCommandLineParser(); return await parser.InvokeAsync(args); -static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, LogLevel minimumLogLevel, string? starredCompletionPath, string? projectRazorJsonFileName, string? telemetryLevel, string? telemetryPath, CancellationToken cancellationToken) +static async Task RunAsync( + bool launchDebugger, + string? brokeredServicePipeName, + LogLevel minimumLogLevel, + string? starredCompletionPath, + string? projectRazorJsonFileName, + string? telemetryLevel, + string? addonsDirectory, + CancellationToken cancellationToken) { // Before we initialize the LSP server we can't send LSP log messages. // Create a console logger as a fallback to use before the LSP server starts. @@ -63,7 +72,7 @@ static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, } } - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(addonsDirectory); // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); @@ -75,7 +84,8 @@ static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, } // Initialize the fault handler if it's available - RoslynLogger.Initialize(telemetryLevel, telemetryPath); + var telemetryReporter = exportProvider.GetExports().SingleOrDefault()?.Value; + RoslynLogger.Initialize(telemetryReporter, telemetryLevel); // Cancellation token source that we can use to cancel on either LSP server shutdown (managed by client) or interrupt. using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -162,9 +172,9 @@ static Parser CreateCommandLineParser() Description = "Telemetry level, Defaults to 'off'. Example values: 'all', 'crash', 'error', or 'off'.", IsRequired = false, }; - var telemetryPathOption = new Option("--telemetryComponentPath") + var addonsDirectoryOption = new Option("--telemetryComponentPath") { - Description = "The location of the telemetry component (if one exists).", + Description = "The directory containing additional Roslyn components (optional).", IsRequired = false }; @@ -186,9 +196,9 @@ static Parser CreateCommandLineParser() var starredCompletionsPath = context.ParseResult.GetValueForOption(starredCompletionsPathOption); var projectRazorJsonFileName = context.ParseResult.GetValueForOption(projectRazorJsonFileNameOption); var telemetryLevel = context.ParseResult.GetValueForOption(telemetryLevelOption); - var telemetryPath = context.ParseResult.GetValueForOption(telemetryPathOption); + var addonsDirectory = context.ParseResult.GetValueForOption(addonsDirectoryOption); - return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, telemetryPath, cancellationToken); + return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, addonsDirectory, cancellationToken); }); return new CommandLineBuilder(rootCommand).UseDefaults().Build(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs deleted file mode 100644 index 31b9c1c778c1c..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/Telemetry/TelemetryService.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.ErrorReporting; - -namespace Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry -{ - internal class TelemetryService : IDisposable - { - private const string AssemblyName = "Microsoft.VisualStudio.LanguageServices.DevKit.dll"; - private const string ClassName = "Microsoft.VisualStudio.LanguageServices.DevKit.VSCodeTelemetryLogger"; - - private readonly AssemblyLoadContextWrapper _alcWrapper; - private readonly Lazy _logMethod; - private readonly Lazy _logBlockStartMethod; - private readonly Lazy _logBlockEndMethod; - private readonly Lazy _reportFaultMethod; - - public TelemetryService(AssemblyLoadContextWrapper alcWrapper) - { - _alcWrapper = alcWrapper; - _logMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "Log")); - _logBlockStartMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "LogBlockStart")); - _logBlockEndMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "LogBlockEnd")); - _reportFaultMethod = new(() => alcWrapper.GetMethodInfo(AssemblyName, ClassName, "ReportFault")); - } - - public static TelemetryService? TryCreate(string telemetryLevel, string location) - { - var alcService = AssemblyLoadContextWrapper.TryCreate("RoslynVSCodeTelemetry", location, logger: null); - if (alcService is null) - { - return null; - } - - var initializeMethod = alcService.TryGetMethodInfo(AssemblyName, ClassName, "Initialize"); - if (initializeMethod is null) - { - return null; - } - - initializeMethod.Invoke(null, new object[] { telemetryLevel }); - return new(alcService); - } - - public void Dispose() - { - _alcWrapper.Dispose(); - } - - internal void Log(string name, ImmutableDictionary properties) - { - _logMethod.Value.Invoke(null, new object[] { name, properties }); - } - - internal void LogBlockStart(string eventName, int kind, int blockId) - { - _logBlockStartMethod.Value.Invoke(null, new object[] { eventName, kind, blockId }); - } - - internal void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) - { - _logBlockEndMethod.Value.Invoke(null, new object[] { blockId, properties, cancellationToken }); - } - - internal void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) - { - _reportFaultMethod.Value.Invoke(null, new object[] { eventName, description, logLevel, forceDump, processId, exception }); - } - } -} diff --git a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs new file mode 100644 index 0000000000000..8c61f49c9b112 --- /dev/null +++ b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs @@ -0,0 +1,182 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis.Contracts.Telemetry; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.Telemetry; + +namespace Microsoft.CodeAnalysis.LanguageServer.Logging; + +[Export(typeof(ITelemetryReporter)), Shared] +internal sealed class VSCodeTelemetryLogger : ITelemetryReporter +{ + private TelemetrySession? _telemetrySession; + private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; + private static int _dumpsSubmitted = 0; + + private static readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); + + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSCodeTelemetryLogger() + { + } + + public void InitializeSession(string telemetryLevel) + { + _telemetrySession?.Dispose(); + _telemetrySession = CreateTelemetryService(telemetryLevel); + _telemetrySession.Start(); + } + + public void Log(string name, ImmutableDictionary properties) + { + var telemetryEvent = new TelemetryEvent(name); + SetProperties(telemetryEvent, properties); + PostEvent(telemetryEvent); + } + + public void LogBlockStart(string eventName, int kind, int blockId) + { + _pendingScopes[blockId] = kind switch + { + 0 => _telemetrySession.StartOperation(eventName), // LogType.Trace + 1 => _telemetrySession.StartUserTask(eventName), // LogType.UserAction + _ => new InvalidOperationException($"Unknown BlockStart kind: {kind}") + }; + } + + public void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) + { + var found = _pendingScopes.TryRemove(blockId, out var scope); + Contract.Requires(found); + + var endEvent = GetEndEvent(scope); + SetProperties(endEvent, properties); + + var result = cancellationToken.IsCancellationRequested ? TelemetryResult.UserCancel : TelemetryResult.Success; + + if (scope is TelemetryScope operation) + operation.End(result); + else if (scope is TelemetryScope userTask) + userTask.End(result); + else + throw new InvalidCastException($"Unexpected value for scope: {scope}"); + } + + public void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) + { + var faultEvent = new FaultEvent( + eventName: eventName, + description: description, + (FaultSeverity)logLevel, + exceptionObject: exception, + gatherEventDetails: faultUtility => + { + if (forceDump) + { + // Let's just send a maximum of three; number chosen arbitrarily + if (Interlocked.Increment(ref _dumpsSubmitted) <= 3) + faultUtility.AddProcessDump(processId); + } + + if (faultUtility is FaultEvent { IsIncludedInWatsonSample: true }) + { + // if needed, add any extra logs here + } + + // Returning "0" signals that, if sampled, we should send data to Watson. + // Any other value will cancel the Watson report. We never want to trigger a process dump manually, + // we'll let TargetedNotifications determine if a dump should be collected. + // See https://aka.ms/roslynnfwdocs for more details + return 0; + }); + + _telemetrySession!.PostEvent(faultEvent); + } + + private static TelemetrySession CreateTelemetryService(string telemetryLevel) + { + var sessionSettingsJson = CreateSessionSettingsJson(telemetryLevel); + TelemetryService.SetDefaultSession(new TelemetrySession($"{{{sessionSettingsJson}}}")); + return TelemetryService.DefaultSession; + } + + private static string CreateSessionSettingsJson(string telemetryLevel) + { + var customSessionId = Guid.NewGuid().ToString(); + + // Generate a new startTime for process to be consumed by Telemetry Settings + using var curProcess = Process.GetCurrentProcess(); + var processStartTime = curProcess.StartTime.ToFileTimeUtc().ToString(); + + var sb = new StringBuilder(); + + var kvp = new Dictionary + { + { "Id", StringToJsonValue(customSessionId) }, + { "HostName", StringToJsonValue("Default") }, + + // Insert Telemetry Level instead of Opt-Out status. The telemetry service handles + // validation of this value so there is no need to do so on this end. If it's invalid, + // it defaults to off. + { "TelemetryLevel", StringToJsonValue(telemetryLevel) }, + + // this sets the Telemetry Session Created by LSP Server to be the Root Initial session + // This means that the SessionID set here by "Id" will be the SessionID used by cloned session + // further down stream + { "IsInitialSession", "true" }, + { "CollectorApiKey", StringToJsonValue(CollectorApiKey) }, + + // using 1010 to indicate VS Code and not to match it to devenv 1000 + { "AppId", "1010" }, + { "ProcessStartTime", processStartTime }, + }; + + foreach (var keyValue in kvp) + { + sb.AppendFormat("\"{0}\":{1},", keyValue.Key, keyValue.Value); + } + + return sb.ToString().TrimEnd(','); + + static string StringToJsonValue(string? value) + { + if (value == null) + { + return "null"; + } + + return '"' + value + '"'; + } + } + + private static TelemetryEvent GetEndEvent(object? scope) + => scope switch + { + TelemetryScope operation => operation.EndEvent, + TelemetryScope userTask => userTask.EndEvent, + _ => throw new InvalidCastException($"Unexpected value for scope: {scope}") + }; + + private void PostEvent(TelemetryEvent telemetryEvent) + => _telemetrySession?.PostEvent(telemetryEvent); + + private static void SetProperties(TelemetryEvent telemetryEvent, ImmutableDictionary properties) + { + foreach (var (name, value) in properties) + { + telemetryEvent.Properties.Add(name, value); + } + } +} diff --git a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj index f96dfa93ebd6d..5c6b3e575ca46 100644 --- a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj +++ b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj @@ -10,6 +10,17 @@ .NET Compiler Platform ("Roslyn") Language Server Protocol internal. + + + + + + + + + DoNotUse + + diff --git a/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs b/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs index 102559fdd0761..8c61f49c9b112 100644 --- a/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs +++ b/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs @@ -6,41 +6,47 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; +using System.Composition; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; using System.Threading; +using Microsoft.CodeAnalysis.Contracts.Telemetry; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Telemetry; -namespace Microsoft.VisualStudio.LanguageServices.DevKit; +namespace Microsoft.CodeAnalysis.LanguageServer.Logging; -internal static class VSCodeTelemetryLogger +[Export(typeof(ITelemetryReporter)), Shared] +internal sealed class VSCodeTelemetryLogger : ITelemetryReporter { - private static TelemetrySession? _telemetrySession; + private TelemetrySession? _telemetrySession; private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; private static int _dumpsSubmitted = 0; private static readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); - public static void Initialize(string telemetryLevel) + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public VSCodeTelemetryLogger() { - if (_telemetrySession is not null) - { - _telemetrySession.Dispose(); - } + } + public void InitializeSession(string telemetryLevel) + { + _telemetrySession?.Dispose(); _telemetrySession = CreateTelemetryService(telemetryLevel); _telemetrySession.Start(); } - public static void Log(string name, ImmutableDictionary properties) + public void Log(string name, ImmutableDictionary properties) { var telemetryEvent = new TelemetryEvent(name); SetProperties(telemetryEvent, properties); PostEvent(telemetryEvent); } - public static void LogBlockStart(string eventName, int kind, int blockId) + public void LogBlockStart(string eventName, int kind, int blockId) { _pendingScopes[blockId] = kind switch { @@ -50,7 +56,7 @@ public static void LogBlockStart(string eventName, int kind, int blockId) }; } - public static void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) + public void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) { var found = _pendingScopes.TryRemove(blockId, out var scope); Contract.Requires(found); @@ -68,7 +74,7 @@ public static void LogBlockEnd(int blockId, ImmutableDictionary throw new InvalidCastException($"Unexpected value for scope: {scope}"); } - public static void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) + public void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) { var faultEvent = new FaultEvent( eventName: eventName, @@ -163,7 +169,7 @@ private static TelemetryEvent GetEndEvent(object? scope) _ => throw new InvalidCastException($"Unexpected value for scope: {scope}") }; - private static void PostEvent(TelemetryEvent telemetryEvent) + private void PostEvent(TelemetryEvent telemetryEvent) => _telemetrySession?.PostEvent(telemetryEvent); private static void SetProperties(TelemetryEvent telemetryEvent, ImmutableDictionary properties) From 007a7b9f19648725b2b7557079f0d24b506d4e9d Mon Sep 17 00:00:00 2001 From: tmat Date: Mon, 1 May 2023 17:06:38 -0700 Subject: [PATCH 214/261] Tests --- Roslyn.sln | 7 -- ...deAnalysis.LanguageServer.UnitTests.csproj | 22 +++++- .../TelemetryReporterTests.cs | 54 +++++++++++++ .../AbstractLanguageServerHostTests.cs | 8 +- .../{ => Utilities}/BrokeredServiceProxy.cs | 0 .../LanguageServerTestComposition.cs | 21 +++++ .../{ => Utilities}/TestOutputLogger.cs | 0 .../{ => Utilities}/Usings.cs | 0 .../WorkspaceProjectFactoryServiceTests.cs | 3 +- .../Contracts/ITelemetryReporter.cs | 2 +- .../Logging/RoslynLogger.cs | 2 +- .../Impl/Logging/VSCodeTelemetryLogger.cs | 79 ++++++++++--------- ...isualStudio.LanguageServices.DevKit.csproj | 10 ++- 13 files changed, 152 insertions(+), 56 deletions(-) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TelemetryReporterTests.cs rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/{ => Utilities}/AbstractLanguageServerHostTests.cs (91%) rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/{ => Utilities}/BrokeredServiceProxy.cs (100%) create mode 100644 src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/{ => Utilities}/TestOutputLogger.cs (100%) rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/{ => Utilities}/Usings.cs (100%) diff --git a/Roslyn.sln b/Roslyn.sln index 43957ca381240..e5ccbc3f28a66 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -541,8 +541,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Feat EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests", "src\Features\VisualBasicTest\Microsoft.CodeAnalysis.VisualBasic.Features.UnitTests.vbproj", "{57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests", "src\VisualStudio\DevKit\Tests\Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests.csproj", "{D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1329,10 +1327,6 @@ Global {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}.Debug|Any CPU.Build.0 = Debug|Any CPU {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}.Release|Any CPU.ActiveCfg = Release|Any CPU {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2}.Release|Any CPU.Build.0 = Release|Any CPU - {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1579,7 +1573,6 @@ Global {E645B517-5766-46FB-AA4A-D4D30C9E3BE6} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} {9296F799-5DE4-4E12-A68E-AAC39B0EB90A} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} {57B7C0AA-E14A-41F6-AD06-FB3937F66FC2} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6} - {D1CA3BE4-4E3F-4AEC-BFDB-739D9418CCCE} = {8DBA5174-B0AA-4561-82B1-A46607697753} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj index 7b88cf4436b03..a8b872f6320d5 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj @@ -11,8 +11,28 @@ + + + - + + + + + + + + + + + + + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TelemetryReporterTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TelemetryReporterTests.cs new file mode 100644 index 0000000000000..b37b653732311 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TelemetryReporterTests.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Contracts.Telemetry; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + +public sealed class TelemetryReporterTests : AbstractLanguageServerHostTests +{ + public TelemetryReporterTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + private static async Task CreateReporterAsync() + { + var exportProvider = await LanguageServerTestComposition.CreateExportProviderAsync(includeDevKitComponents: true); + + var reporter = exportProvider.GetExport().Value; + Assert.NotNull(reporter); + + // Do not set default session in tests to enable test isolation: + reporter.InitializeSession("off", isDefaultSession: false); + + return reporter; + } + + private static string GetEventName(string name) => $"test/event/{name}"; + + [Fact] + public async Task TestFault() + { + var service = await CreateReporterAsync(); + service.ReportFault(GetEventName(nameof(TestFault)), "test description", logLevel: 2, forceDump: false, processId: 0, new Exception()); + } + + [Fact] + public async Task TestBlockLogging() + { + var service = await CreateReporterAsync(); + service.LogBlockStart(GetEventName(nameof(TestBlockLogging)), kind: 0, blockId: 0); + service.LogBlockEnd(blockId: 0, ImmutableDictionary.Empty, CancellationToken.None); + } + + [Fact] + public async Task TestLog() + { + var service = await CreateReporterAsync(); + service.Log(GetEventName(nameof(TestLog)), ImmutableDictionary.Empty); + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs similarity index 91% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs index fb8cd3e84a46a..e77acefa08299 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs @@ -21,9 +21,9 @@ protected AbstractLanguageServerHostTests(ITestOutputHelper testOutputHelper) TestOutputLogger = new TestOutputLogger(testOutputHelper); } - protected Task CreateLanguageServerAsync() + protected Task CreateLanguageServerAsync(bool includeDevKitComponents = true) { - return TestLspServer.CreateAsync(new ClientCapabilities(), TestOutputLogger); + return TestLspServer.CreateAsync(new ClientCapabilities(), TestOutputLogger, includeDevKitComponents); } protected sealed class TestLspServer : IAsyncDisposable @@ -31,9 +31,9 @@ protected sealed class TestLspServer : IAsyncDisposable private readonly Task _languageServerHostCompletionTask; private readonly JsonRpc _clientRpc; - public static async Task CreateAsync(ClientCapabilities clientCapabilities, ILogger logger) + public static async Task CreateAsync(ClientCapabilities clientCapabilities, ILogger logger, bool includeDevKitComponents = true) { - var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + var exportProvider = await LanguageServerTestComposition.CreateExportProviderAsync(includeDevKitComponents); var testLspServer = new TestLspServer(exportProvider, logger); var initializeResponse = await testLspServer.ExecuteRequestAsync(Methods.InitializeName, new InitializeParams { Capabilities = clientCapabilities }, CancellationToken.None); Assert.NotNull(initializeResponse?.Capabilities); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/BrokeredServiceProxy.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/BrokeredServiceProxy.cs similarity index 100% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/BrokeredServiceProxy.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/BrokeredServiceProxy.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs new file mode 100644 index 0000000000000..f58ad6f8e3cef --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + +internal sealed class LanguageServerTestComposition +{ + /// + /// Build places DevKit files to this subdirectory. + /// + private const string DevKitExtensionSubdirectory = "DevKit"; + + private static string GetDevKitExtensionDirectory() + => Path.Combine(AppContext.BaseDirectory, DevKitExtensionSubdirectory); + + public static Task CreateExportProviderAsync(bool includeDevKitComponents) + => ExportProviderBuilder.CreateExportProviderAsync(addonsDirectory: includeDevKitComponents ? GetDevKitExtensionDirectory() : null); +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TestOutputLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/TestOutputLogger.cs similarity index 100% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/TestOutputLogger.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/TestOutputLogger.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Usings.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/Usings.cs similarity index 100% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Usings.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/Usings.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs index 974c077b76be2..5a83734ad8321 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs @@ -9,12 +9,13 @@ using Microsoft.VisualStudio.Shell.ServiceBroker; namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; + public class WorkspaceProjectFactoryServiceTests { [Fact] public async Task CreateProjectAndBatch() { - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + using var exportProvider = await LanguageServerTestComposition.CreateExportProviderAsync(includeDevKitComponents: false); exportProvider.GetExportedValue().SetFactory(new LoggerFactory()); var workspaceFactory = exportProvider.GetExportedValue(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs index 59c3e818563ec..c2dc9f826308c 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Contracts/ITelemetryReporter.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Contracts.Telemetry; internal interface ITelemetryReporter { - void InitializeSession(string telemetryLevel); + void InitializeSession(string telemetryLevel, bool isDefaultSession); void Log(string name, ImmutableDictionary properties); void LogBlockStart(string eventName, int kind, int blockId); void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs index e41677f5873f6..de1c229ac0788 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/RoslynLogger.cs @@ -39,7 +39,7 @@ public static void Initialize(ITelemetryReporter? reporter, string? telemetryLev if (reporter is not null && telemetryLevel is not null) { - reporter.InitializeSession(telemetryLevel); + reporter.InitializeSession(telemetryLevel, isDefaultSession: true); _telemetryReporter = reporter; } diff --git a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs index 8c61f49c9b112..df4d891934a6a 100644 --- a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs +++ b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs @@ -8,7 +8,6 @@ using System.Collections.Immutable; using System.Composition; using System.Diagnostics; -using System.Diagnostics.Contracts; using System.Text; using System.Threading; using Microsoft.CodeAnalysis.Contracts.Telemetry; @@ -32,22 +31,36 @@ public VSCodeTelemetryLogger() { } - public void InitializeSession(string telemetryLevel) + public void InitializeSession(string telemetryLevel, bool isDefaultSession) { - _telemetrySession?.Dispose(); - _telemetrySession = CreateTelemetryService(telemetryLevel); - _telemetrySession.Start(); + Debug.Assert(_telemetrySession == null); + + var sessionSettingsJson = CreateSessionSettingsJson(telemetryLevel); + var session = new TelemetrySession($"{{{sessionSettingsJson}}}"); + + if (isDefaultSession) + { + TelemetryService.SetDefaultSession(session); + } + + session.Start(); + + _telemetrySession = session; } public void Log(string name, ImmutableDictionary properties) { + Debug.Assert(_telemetrySession != null); + var telemetryEvent = new TelemetryEvent(name); SetProperties(telemetryEvent, properties); - PostEvent(telemetryEvent); + _telemetrySession.PostEvent(telemetryEvent); } public void LogBlockStart(string eventName, int kind, int blockId) { + Debug.Assert(_telemetrySession != null); + _pendingScopes[blockId] = kind switch { 0 => _telemetrySession.StartOperation(eventName), // LogType.Trace @@ -59,7 +72,7 @@ public void LogBlockStart(string eventName, int kind, int blockId) public void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) { var found = _pendingScopes.TryRemove(blockId, out var scope); - Contract.Requires(found); + Debug.Assert(found); var endEvent = GetEndEvent(scope); SetProperties(endEvent, properties); @@ -76,6 +89,8 @@ public void LogBlockEnd(int blockId, ImmutableDictionary proper public void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) { + Debug.Assert(_telemetrySession != null); + var faultEvent = new FaultEvent( eventName: eventName, description: description, @@ -102,14 +117,7 @@ public void ReportFault(string eventName, string description, int logLevel, bool return 0; }); - _telemetrySession!.PostEvent(faultEvent); - } - - private static TelemetrySession CreateTelemetryService(string telemetryLevel) - { - var sessionSettingsJson = CreateSessionSettingsJson(telemetryLevel); - TelemetryService.SetDefaultSession(new TelemetrySession($"{{{sessionSettingsJson}}}")); - return TelemetryService.DefaultSession; + _telemetrySession.PostEvent(faultEvent); } private static string CreateSessionSettingsJson(string telemetryLevel) @@ -123,25 +131,25 @@ private static string CreateSessionSettingsJson(string telemetryLevel) var sb = new StringBuilder(); var kvp = new Dictionary - { - { "Id", StringToJsonValue(customSessionId) }, - { "HostName", StringToJsonValue("Default") }, - - // Insert Telemetry Level instead of Opt-Out status. The telemetry service handles - // validation of this value so there is no need to do so on this end. If it's invalid, - // it defaults to off. - { "TelemetryLevel", StringToJsonValue(telemetryLevel) }, - - // this sets the Telemetry Session Created by LSP Server to be the Root Initial session - // This means that the SessionID set here by "Id" will be the SessionID used by cloned session - // further down stream - { "IsInitialSession", "true" }, - { "CollectorApiKey", StringToJsonValue(CollectorApiKey) }, - - // using 1010 to indicate VS Code and not to match it to devenv 1000 - { "AppId", "1010" }, - { "ProcessStartTime", processStartTime }, - }; + { + { "Id", StringToJsonValue(customSessionId) }, + { "HostName", StringToJsonValue("Default") }, + + // Insert Telemetry Level instead of Opt-Out status. The telemetry service handles + // validation of this value so there is no need to do so on this end. If it's invalid, + // it defaults to off. + { "TelemetryLevel", StringToJsonValue(telemetryLevel) }, + + // this sets the Telemetry Session Created by LSP Server to be the Root Initial session + // This means that the SessionID set here by "Id" will be the SessionID used by cloned session + // further down stream + { "IsInitialSession", "true" }, + { "CollectorApiKey", StringToJsonValue(CollectorApiKey) }, + + // using 1010 to indicate VS Code and not to match it to devenv 1000 + { "AppId", "1010" }, + { "ProcessStartTime", processStartTime }, + }; foreach (var keyValue in kvp) { @@ -169,9 +177,6 @@ private static TelemetryEvent GetEndEvent(object? scope) _ => throw new InvalidCastException($"Unexpected value for scope: {scope}") }; - private void PostEvent(TelemetryEvent telemetryEvent) - => _telemetrySession?.PostEvent(telemetryEvent); - private static void SetProperties(TelemetryEvent telemetryEvent, ImmutableDictionary properties) { foreach (var (name, value) in properties) diff --git a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj index 5c6b3e575ca46..a58d8b0d44e75 100644 --- a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj +++ b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj @@ -15,8 +15,10 @@ - + + + DoNotUse @@ -51,9 +53,9 @@ - - - + + + From 5ed4c920216fd29a3109ab438fc2ecd5f168667d Mon Sep 17 00:00:00 2001 From: tmat Date: Mon, 1 May 2023 17:34:01 -0700 Subject: [PATCH 215/261] Fix merge --- ...deAnalysis.LanguageServer.UnitTests.csproj | 4 +- .../LanguageServerTestComposition.cs | 2 +- .../ExportProviderBuilder.cs | 10 +- ...crosoft.CodeAnalysis.LanguageServer.csproj | 2 +- .../Program.cs | 10 +- .../DevKit/Impl/VSCodeTelemetryLogger.cs | 182 ------------------ ...o.LanguageServices.DevKit.UnitTests.csproj | 34 ---- .../Tests/VSCodeTelemetryLoggerTests.cs | 55 ------ 8 files changed, 14 insertions(+), 285 deletions(-) delete mode 100644 src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs delete mode 100644 src/VisualStudio/DevKit/Tests/Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests.csproj delete mode 100644 src/VisualStudio/DevKit/Tests/VSCodeTelemetryLoggerTests.cs diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj index a8b872f6320d5..e6b567e3e8067 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj @@ -17,7 +17,7 @@ - @@ -26,7 +26,7 @@ Copy files contained in the NPM package to a DevKit subdirectory to emulate deployment of the DevKit extension in VS Code. --> - diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs index f58ad6f8e3cef..115c52dcbaf92 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs @@ -17,5 +17,5 @@ private static string GetDevKitExtensionDirectory() => Path.Combine(AppContext.BaseDirectory, DevKitExtensionSubdirectory); public static Task CreateExportProviderAsync(bool includeDevKitComponents) - => ExportProviderBuilder.CreateExportProviderAsync(addonsDirectory: includeDevKitComponents ? GetDevKitExtensionDirectory() : null); + => ExportProviderBuilder.CreateExportProviderAsync(devKitDirectory: includeDevKitComponents ? GetDevKitExtensionDirectory() : null); } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 29703b1e53254..f525e00f890c8 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -14,9 +14,9 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal sealed class ExportProviderBuilder { - private const string AddonsAssemblyFileName = "Microsoft.CodeAnalysis.LanguageServer.Internal.dll"; + private const string DevKitAssemblyFileName = "Microsoft.VisualStudio.LanguageServices.DevKit.dll"; - public static async Task CreateExportProviderAsync(string? addonsDirectory) + public static async Task CreateExportProviderAsync(string? devKitDirectory) { var baseDirectory = AppContext.BaseDirectory; @@ -47,12 +47,12 @@ public static async Task CreateExportProviderAsync(string? addon }; // Additional Roslyn services: - if (addonsDirectory != null) + if (devKitDirectory != null) { - var loadContext = AssemblyLoadContextWrapper.TryCreate(name: "CodeAnalysisAddons", addonsDirectory, logger: null); + var loadContext = AssemblyLoadContextWrapper.TryCreate(name: "CodeAnalysisAddons", devKitDirectory, logger: null); if (loadContext != null) { - assemblies.Add(loadContext.GetAssembly(AddonsAssemblyFileName)); + assemblies.Add(loadContext.GetAssembly(DevKitAssemblyFileName)); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index 3b00d3496de14..e629e6d4a436b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -71,7 +71,7 @@ Only allow C# DevKit to use types from Microsoft.CodeAnalysis.Contracts namespace. The contracts should not introduce breaking changes between versions, because the versions of C# DevKit and C# Extension might not be aligned. --> - + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index eee376e5ee225..d1a915ea3570d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -31,7 +31,7 @@ string? starredCompletionPath, string? projectRazorJsonFileName, string? telemetryLevel, - string? addonsDirectory, + string? devKitDirectory, CancellationToken cancellationToken) { // Before we initialize the LSP server we can't send LSP log messages. @@ -72,7 +72,7 @@ } } - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(addonsDirectory); + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(devKitDirectory); // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); @@ -172,7 +172,7 @@ static Parser CreateCommandLineParser() Description = "Telemetry level, Defaults to 'off'. Example values: 'all', 'crash', 'error', or 'off'.", IsRequired = false, }; - var addonsDirectoryOption = new Option("--telemetryComponentPath") + var devKitDirectoryOption = new Option("--telemetryComponentPath") { Description = "The directory containing additional Roslyn components (optional).", IsRequired = false @@ -196,9 +196,9 @@ static Parser CreateCommandLineParser() var starredCompletionsPath = context.ParseResult.GetValueForOption(starredCompletionsPathOption); var projectRazorJsonFileName = context.ParseResult.GetValueForOption(projectRazorJsonFileNameOption); var telemetryLevel = context.ParseResult.GetValueForOption(telemetryLevelOption); - var addonsDirectory = context.ParseResult.GetValueForOption(addonsDirectoryOption); + var devKitDirectory = context.ParseResult.GetValueForOption(devKitDirectoryOption); - return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, addonsDirectory, cancellationToken); + return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, devKitDirectory, cancellationToken); }); return new CommandLineBuilder(rootCommand).UseDefaults().Build(); diff --git a/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs b/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs deleted file mode 100644 index 8c61f49c9b112..0000000000000 --- a/src/VisualStudio/DevKit/Impl/VSCodeTelemetryLogger.cs +++ /dev/null @@ -1,182 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Text; -using System.Threading; -using Microsoft.CodeAnalysis.Contracts.Telemetry; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.VisualStudio.Telemetry; - -namespace Microsoft.CodeAnalysis.LanguageServer.Logging; - -[Export(typeof(ITelemetryReporter)), Shared] -internal sealed class VSCodeTelemetryLogger : ITelemetryReporter -{ - private TelemetrySession? _telemetrySession; - private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; - private static int _dumpsSubmitted = 0; - - private static readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSCodeTelemetryLogger() - { - } - - public void InitializeSession(string telemetryLevel) - { - _telemetrySession?.Dispose(); - _telemetrySession = CreateTelemetryService(telemetryLevel); - _telemetrySession.Start(); - } - - public void Log(string name, ImmutableDictionary properties) - { - var telemetryEvent = new TelemetryEvent(name); - SetProperties(telemetryEvent, properties); - PostEvent(telemetryEvent); - } - - public void LogBlockStart(string eventName, int kind, int blockId) - { - _pendingScopes[blockId] = kind switch - { - 0 => _telemetrySession.StartOperation(eventName), // LogType.Trace - 1 => _telemetrySession.StartUserTask(eventName), // LogType.UserAction - _ => new InvalidOperationException($"Unknown BlockStart kind: {kind}") - }; - } - - public void LogBlockEnd(int blockId, ImmutableDictionary properties, CancellationToken cancellationToken) - { - var found = _pendingScopes.TryRemove(blockId, out var scope); - Contract.Requires(found); - - var endEvent = GetEndEvent(scope); - SetProperties(endEvent, properties); - - var result = cancellationToken.IsCancellationRequested ? TelemetryResult.UserCancel : TelemetryResult.Success; - - if (scope is TelemetryScope operation) - operation.End(result); - else if (scope is TelemetryScope userTask) - userTask.End(result); - else - throw new InvalidCastException($"Unexpected value for scope: {scope}"); - } - - public void ReportFault(string eventName, string description, int logLevel, bool forceDump, int processId, Exception exception) - { - var faultEvent = new FaultEvent( - eventName: eventName, - description: description, - (FaultSeverity)logLevel, - exceptionObject: exception, - gatherEventDetails: faultUtility => - { - if (forceDump) - { - // Let's just send a maximum of three; number chosen arbitrarily - if (Interlocked.Increment(ref _dumpsSubmitted) <= 3) - faultUtility.AddProcessDump(processId); - } - - if (faultUtility is FaultEvent { IsIncludedInWatsonSample: true }) - { - // if needed, add any extra logs here - } - - // Returning "0" signals that, if sampled, we should send data to Watson. - // Any other value will cancel the Watson report. We never want to trigger a process dump manually, - // we'll let TargetedNotifications determine if a dump should be collected. - // See https://aka.ms/roslynnfwdocs for more details - return 0; - }); - - _telemetrySession!.PostEvent(faultEvent); - } - - private static TelemetrySession CreateTelemetryService(string telemetryLevel) - { - var sessionSettingsJson = CreateSessionSettingsJson(telemetryLevel); - TelemetryService.SetDefaultSession(new TelemetrySession($"{{{sessionSettingsJson}}}")); - return TelemetryService.DefaultSession; - } - - private static string CreateSessionSettingsJson(string telemetryLevel) - { - var customSessionId = Guid.NewGuid().ToString(); - - // Generate a new startTime for process to be consumed by Telemetry Settings - using var curProcess = Process.GetCurrentProcess(); - var processStartTime = curProcess.StartTime.ToFileTimeUtc().ToString(); - - var sb = new StringBuilder(); - - var kvp = new Dictionary - { - { "Id", StringToJsonValue(customSessionId) }, - { "HostName", StringToJsonValue("Default") }, - - // Insert Telemetry Level instead of Opt-Out status. The telemetry service handles - // validation of this value so there is no need to do so on this end. If it's invalid, - // it defaults to off. - { "TelemetryLevel", StringToJsonValue(telemetryLevel) }, - - // this sets the Telemetry Session Created by LSP Server to be the Root Initial session - // This means that the SessionID set here by "Id" will be the SessionID used by cloned session - // further down stream - { "IsInitialSession", "true" }, - { "CollectorApiKey", StringToJsonValue(CollectorApiKey) }, - - // using 1010 to indicate VS Code and not to match it to devenv 1000 - { "AppId", "1010" }, - { "ProcessStartTime", processStartTime }, - }; - - foreach (var keyValue in kvp) - { - sb.AppendFormat("\"{0}\":{1},", keyValue.Key, keyValue.Value); - } - - return sb.ToString().TrimEnd(','); - - static string StringToJsonValue(string? value) - { - if (value == null) - { - return "null"; - } - - return '"' + value + '"'; - } - } - - private static TelemetryEvent GetEndEvent(object? scope) - => scope switch - { - TelemetryScope operation => operation.EndEvent, - TelemetryScope userTask => userTask.EndEvent, - _ => throw new InvalidCastException($"Unexpected value for scope: {scope}") - }; - - private void PostEvent(TelemetryEvent telemetryEvent) - => _telemetrySession?.PostEvent(telemetryEvent); - - private static void SetProperties(TelemetryEvent telemetryEvent, ImmutableDictionary properties) - { - foreach (var (name, value) in properties) - { - telemetryEvent.Properties.Add(name, value); - } - } -} diff --git a/src/VisualStudio/DevKit/Tests/Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests.csproj b/src/VisualStudio/DevKit/Tests/Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests.csproj deleted file mode 100644 index e802ad04ec9e9..0000000000000 --- a/src/VisualStudio/DevKit/Tests/Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - Library - net7.0 - Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests - UnitTest - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VisualStudio/DevKit/Tests/VSCodeTelemetryLoggerTests.cs b/src/VisualStudio/DevKit/Tests/VSCodeTelemetryLoggerTests.cs deleted file mode 100644 index 0c37672b4a4d3..0000000000000 --- a/src/VisualStudio/DevKit/Tests/VSCodeTelemetryLoggerTests.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -using System; -using System.Collections.Immutable; -using System.IO; -using System.Threading; -using Microsoft.CodeAnalysis.LanguageServer.Services; -using Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry; -using Microsoft.VisualStudio.Telemetry; -using Xunit; -using TelemetryService = Microsoft.CodeAnalysis.LanguageServer.Services.Telemetry.TelemetryService; - -namespace Microsoft.VisualStudio.LanguageServices.DevKit.UnitTests; - -public class VSCodeTelemetryLoggerTests -{ - private static TelemetryService CreateService() - { - var assembly = typeof(VSCodeTelemetryLogger).Assembly; - var telemetryDirectory = new FileInfo(assembly.Location).Directory.FullName; - var service = TelemetryService.TryCreate("off", telemetryDirectory); - - Assert.NotNull(service); - - return service; - } - - private static string GetEventName(string name) => $"test/event/{name}"; - - [Fact] - public void TestFault() - { - var service = CreateService(); - service.ReportFault(GetEventName(nameof(TestFault)), "test description", (int)FaultSeverity.General, forceDump: false, processId: 0, new Exception()); - } - - [Fact] - public void TestBlockLogging() - { - var service = CreateService(); - service.LogBlockStart(GetEventName(nameof(TestBlockLogging)), kind: 0, blockId: 0); - service.LogBlockEnd(blockId: 0, ImmutableDictionary.Empty, CancellationToken.None); - } - - [Fact] - public void TestLog() - { - var service = CreateService(); - service.Log(GetEventName(nameof(TestLog)), ImmutableDictionary.Empty); - } -} From 96bef142b76d9a295f8228b5cae942a8cf83151a Mon Sep 17 00:00:00 2001 From: tmat Date: Mon, 1 May 2023 17:44:14 -0700 Subject: [PATCH 216/261] Rename option --- .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index d1a915ea3570d..9576de9937680 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -172,9 +172,9 @@ static Parser CreateCommandLineParser() Description = "Telemetry level, Defaults to 'off'. Example values: 'all', 'crash', 'error', or 'off'.", IsRequired = false, }; - var devKitDirectoryOption = new Option("--telemetryComponentPath") + var devKitDirectoryOption = new Option("--devKitDirectory") { - Description = "The directory containing additional Roslyn components (optional).", + Description = "The directory containing C# DevKit extension (optional).", IsRequired = false }; From 91777736fd8b99e2086dcb117252e90608aed0e3 Mon Sep 17 00:00:00 2001 From: tmat Date: Mon, 1 May 2023 17:45:46 -0700 Subject: [PATCH 217/261] Rename --- .../ExportProviderBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index f525e00f890c8..6bf99dbca152b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -49,7 +49,7 @@ public static async Task CreateExportProviderAsync(string? devKi // Additional Roslyn services: if (devKitDirectory != null) { - var loadContext = AssemblyLoadContextWrapper.TryCreate(name: "CodeAnalysisAddons", devKitDirectory, logger: null); + var loadContext = AssemblyLoadContextWrapper.TryCreate(name: "C# DevKit", devKitDirectory, logger: null); if (loadContext != null) { assemblies.Add(loadContext.GetAssembly(DevKitAssemblyFileName)); From 4530a8d642bcf2ee771326acc000a830043dca92 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 2 May 2023 11:50:08 +1000 Subject: [PATCH 218/261] More PR feedback --- .../RazorWorkspaceListenerInitializer.cs | 64 ++++++++----------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs index 97d45b607b9e3..cb26c0a5149b7 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs @@ -23,9 +23,12 @@ internal sealed class RazorWorkspaceListenerInitializer private const string _projectRazorJsonFileName = "project.razor.vscode.json"; private readonly ILogger _logger; - private readonly Lazy _razorWorkspaceListener; - private ImmutableHashSet _projectIdWithDynamicFiles = ImmutableHashSet.Empty; + private readonly HashSet _projectIdWithDynamicFiles = new(); private readonly object _initializeGate = new(); + private readonly Lazy _workspaceFactory; + private readonly ILoggerFactory _loggerFactory; + + private RazorWorkspaceListener? _razorWorkspaceListener; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -33,68 +36,51 @@ public RazorWorkspaceListenerInitializer(Lazy wo { _logger = loggerFactory.CreateLogger(nameof(RazorWorkspaceListenerInitializer)); - _razorWorkspaceListener = new Lazy(() => - { - var razorWorkspaceListener = new RazorWorkspaceListener(loggerFactory); - var workspace = workspaceFactory.Value.Workspace; - razorWorkspaceListener.EnsureInitialized(workspace, _projectRazorJsonFileName); - - return razorWorkspaceListener; - }); + _workspaceFactory = workspaceFactory; + _loggerFactory = loggerFactory; } internal void Initialize() { - // Only initialize once - if (_razorWorkspaceListener.IsValueCreated) - { - return; - } - - ImmutableHashSet projectsToProcess; lock (_initializeGate) { - if (_razorWorkspaceListener.IsValueCreated) + // Only initialize once + if (_razorWorkspaceListener is not null) { return; } _logger.LogTrace("Initializing the Razor workspace listener"); - _ = _razorWorkspaceListener.Value; - projectsToProcess = Interlocked.Exchange(ref _projectIdWithDynamicFiles, ImmutableHashSet.Empty); + _razorWorkspaceListener = new RazorWorkspaceListener(_loggerFactory); + _razorWorkspaceListener.EnsureInitialized(_workspaceFactory.Value.Workspace, _projectRazorJsonFileName); } - foreach (var projectId in projectsToProcess) + foreach (var projectId in _projectIdWithDynamicFiles) { _logger.LogTrace("{projectId} notifying a dynamic file for the first time", projectId); - _razorWorkspaceListener.Value.NotifyDynamicFile(projectId); + _razorWorkspaceListener.NotifyDynamicFile(projectId); } + + // May as well clear out the collection, it will never get used again anyway. + _projectIdWithDynamicFiles.Clear(); } internal void NotifyDynamicFile(ProjectId projectId) { - if (!_razorWorkspaceListener.IsValueCreated) + lock (_initializeGate) { - // We haven't been initialized by the extension yet, so just store the project id, to tell Razor later - _logger.LogTrace("{projectId} queuing up a dynamic file notify for later", projectId); - ImmutableInterlocked.Update(ref _projectIdWithDynamicFiles, (col, arg) => col.Add(arg), projectId); + if (_razorWorkspaceListener is null) + { + // We haven't been initialized by the extension yet, so just store the project id, to tell Razor later + _logger.LogTrace("{projectId} queuing up a dynamic file notify for later", projectId); + _projectIdWithDynamicFiles.Add(projectId); - return; + return; + } } // We've been initialized, so just pass the information along _logger.LogTrace("{projectId} forwarding on a dynamic file notification because we're initialized", projectId); - _razorWorkspaceListener.Value.NotifyDynamicFile(projectId); - - // It's possible that we were initialized after the IsValueCreated check above, which could leave stale project Ids in - // our hashset, so we'll see if we need to clear it out just in case - if (!_projectIdWithDynamicFiles.IsEmpty) - { - var projects = Interlocked.Exchange(ref _projectIdWithDynamicFiles, ImmutableHashSet.Empty); - foreach (var pId in projects) - { - _razorWorkspaceListener.Value.NotifyDynamicFile(pId); - } - } + _razorWorkspaceListener.NotifyDynamicFile(projectId); } } From 7c4b6d1dc30a9e1ff8bf631178fd957bf399fa74 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Tue, 2 May 2023 04:18:38 +0000 Subject: [PATCH 219/261] Merged PR 30981: Update npmrc path The npmrc file was moved and the pipelines were not updated. --- azure-pipelines-official.yml | 4 ++-- eng/publish-assets.ps1 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 42e1282adc960..8608c261a6c6e 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -330,10 +330,10 @@ stages: - task: npmAuthenticate@0 displayName: Authenticate NPM Feed inputs: - workingFile: $(Build.SourcesDirectory)/src/VisualStudio/LanguageServer/Impl/.npmrc + workingFile: $(Build.SourcesDirectory)/src/VisualStudio/DevKit/Impl/.npmrc customEndpoint: devdiv-vs-green-npm-package-feed - - script: npm publish --userconfig $(Build.SourcesDirectory)\src\VisualStudio\LanguageServer\Impl\.npmrc $(NPMFileName) + - script: npm publish --userconfig $(Build.SourcesDirectory)\src\VisualStudio\DevKit\Impl\.npmrc $(NPMFileName) displayName: Publish Language Server NPM Package # Publish Asset Manifests for Build Asset Registry job diff --git a/eng/publish-assets.ps1 b/eng/publish-assets.ps1 index 13cfdd3b94799..3a9ba8f0fb227 100644 --- a/eng/publish-assets.ps1 +++ b/eng/publish-assets.ps1 @@ -120,7 +120,7 @@ function Publish-Npm([string]$npmPackagesDir) { Write-Host "" Write-Host "Publishing NPM packages in $npmPackagesDir..." - $npmrcPath = [IO.Path]::Combine($RepoRoot, "src", "VisualStudio", "Microsoft.VisualStudio.LanguageServices.DevKit", ".npmrc") + $npmrcPath = [IO.Path]::Combine($RepoRoot, "src", "VisualStudio", "DevKit", "Impl", ".npmrc") if (-not (Test-Path $npmrcPath)) { throw "Missing .npmrc at $npmrcPath" } From d043301bf3e086f0119871827fe18c139040e11b Mon Sep 17 00:00:00 2001 From: tmat Date: Tue, 2 May 2023 09:46:27 -0700 Subject: [PATCH 220/261] Generalize extension loading --- .../LanguageServerTestComposition.cs | 8 ++++--- .../ExportProviderBuilder.cs | 12 ++++------ .../Program.cs | 12 +++++----- .../Services/AssemblyLoadContextWrapper.cs | 24 +++++++++++++++++++ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs index 115c52dcbaf92..f718852c85c03 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs @@ -13,9 +13,11 @@ internal sealed class LanguageServerTestComposition /// private const string DevKitExtensionSubdirectory = "DevKit"; - private static string GetDevKitExtensionDirectory() - => Path.Combine(AppContext.BaseDirectory, DevKitExtensionSubdirectory); + private const string DevKitAssemblyFileName = "Microsoft.VisualStudio.LanguageServices.DevKit.dll"; + + private static string GetDevKitExtensionPath() + => Path.Combine(AppContext.BaseDirectory, DevKitExtensionSubdirectory, DevKitAssemblyFileName); public static Task CreateExportProviderAsync(bool includeDevKitComponents) - => ExportProviderBuilder.CreateExportProviderAsync(devKitDirectory: includeDevKitComponents ? GetDevKitExtensionDirectory() : null); + => ExportProviderBuilder.CreateExportProviderAsync(extensionAssemblyPaths: includeDevKitComponents ? new[] { GetDevKitExtensionPath() } : Array.Empty()); } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index 6bf99dbca152b..653b52bd0093b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -14,9 +14,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal sealed class ExportProviderBuilder { - private const string DevKitAssemblyFileName = "Microsoft.VisualStudio.LanguageServices.DevKit.dll"; - - public static async Task CreateExportProviderAsync(string? devKitDirectory) + public static async Task CreateExportProviderAsync(IEnumerable extensionAssemblyPaths) { var baseDirectory = AppContext.BaseDirectory; @@ -46,13 +44,11 @@ public static async Task CreateExportProviderAsync(string? devKi typeof(ExportProviderBuilder).Assembly }; - // Additional Roslyn services: - if (devKitDirectory != null) + foreach (var extensionAssemblyPath in extensionAssemblyPaths) { - var loadContext = AssemblyLoadContextWrapper.TryCreate(name: "C# DevKit", devKitDirectory, logger: null); - if (loadContext != null) + if (AssemblyLoadContextWrapper.TryLoadExtension(extensionAssemblyPath, logger: null, out var extensionAssembly)) { - assemblies.Add(loadContext.GetAssembly(DevKitAssemblyFileName)); + assemblies.Add(extensionAssembly); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 9576de9937680..2802235e33797 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -31,7 +31,7 @@ string? starredCompletionPath, string? projectRazorJsonFileName, string? telemetryLevel, - string? devKitDirectory, + IEnumerable extensionAssemblyPaths, CancellationToken cancellationToken) { // Before we initialize the LSP server we can't send LSP log messages. @@ -72,7 +72,7 @@ } } - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(devKitDirectory); + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(extensionAssemblyPaths); // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); @@ -172,9 +172,9 @@ static Parser CreateCommandLineParser() Description = "Telemetry level, Defaults to 'off'. Example values: 'all', 'crash', 'error', or 'off'.", IsRequired = false, }; - var devKitDirectoryOption = new Option("--devKitDirectory") + var extensionAssemblyPathsOption = new Option("--extensions") { - Description = "The directory containing C# DevKit extension (optional).", + Description = "Full paths of extension assemblies to load (optional).", IsRequired = false }; @@ -196,9 +196,9 @@ static Parser CreateCommandLineParser() var starredCompletionsPath = context.ParseResult.GetValueForOption(starredCompletionsPathOption); var projectRazorJsonFileName = context.ParseResult.GetValueForOption(projectRazorJsonFileNameOption); var telemetryLevel = context.ParseResult.GetValueForOption(telemetryLevelOption); - var devKitDirectory = context.ParseResult.GetValueForOption(devKitDirectoryOption); + var extensionAssemblyPaths = context.ParseResult.GetValueForOption(extensionAssemblyPathsOption) ?? Array.Empty(); - return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, devKitDirectory, cancellationToken); + return RunAsync(launchDebugger, brokeredServicePipeName, logLevel, starredCompletionsPath, projectRazorJsonFileName, telemetryLevel, extensionAssemblyPaths, cancellationToken); }); return new CommandLineBuilder(rootCommand).UseDefaults().Build(); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs index fca4ace4e7c73..a566e0282d0b9 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs @@ -5,12 +5,15 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.Loader; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Services { @@ -27,6 +30,27 @@ private AssemblyLoadContextWrapper(AssemblyLoadContext assemblyLoadContext, Immu _logger = logger; } + public static bool TryLoadExtension(string assemblyFilePath, ILogger? logger, [NotNullWhen(true)] out Assembly? assembly) + { + var dir = Path.GetDirectoryName(assemblyFilePath); + var fileName = Path.GetFileName(assemblyFilePath); + var fileNameNoExt = Path.GetFileNameWithoutExtension(assemblyFilePath); + + Contract.ThrowIfNull(dir); + Contract.ThrowIfNull(fileName); + Contract.ThrowIfNull(fileNameNoExt); + + var loadContext = TryCreate(fileNameNoExt, dir, logger); + if (loadContext != null) + { + assembly = loadContext.GetAssembly(fileName); + return true; + } + + assembly = null; + return false; + } + public static AssemblyLoadContextWrapper? TryCreate(string name, string assembliesDirectoryPath, ILogger? logger) { try From 73439a66f9a42b4920cd6f693b7cba9c8b4ce97f Mon Sep 17 00:00:00 2001 From: tmat Date: Tue, 2 May 2023 15:26:34 -0700 Subject: [PATCH 221/261] Fix formatting --- src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs index df4d891934a6a..8e30e93feb2fe 100644 --- a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs +++ b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs @@ -60,7 +60,7 @@ public void Log(string name, ImmutableDictionary properties) public void LogBlockStart(string eventName, int kind, int blockId) { Debug.Assert(_telemetrySession != null); - + _pendingScopes[blockId] = kind switch { 0 => _telemetrySession.StartOperation(eventName), // LogType.Trace From 318d85f55cfc569523c7390def74c0601b75bb0a Mon Sep 17 00:00:00 2001 From: tmat Date: Tue, 2 May 2023 16:57:43 -0700 Subject: [PATCH 222/261] Fixes --- .../Microsoft.CodeAnalysis.LanguageServer/Program.cs | 1 + .../Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 2802235e33797..b28882e595070 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -186,6 +186,7 @@ static Parser CreateCommandLineParser() starredCompletionsPathOption, projectRazorJsonFileNameOption, telemetryLevelOption, + extensionAssemblyPathsOption, }; rootCommand.SetHandler(context => { diff --git a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj index a58d8b0d44e75..ac312c598aea0 100644 --- a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj +++ b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj @@ -58,7 +58,7 @@ - + From 915f3c384c8fb99d9726ddeb190015ce03d58949 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 2 May 2023 16:59:48 -0700 Subject: [PATCH 223/261] Improve logging of mef composition failures --- .../AbstractLanguageServerHostTests.cs | 22 ++++++++++++++++++- .../WorkspaceProjectFactoryServiceTests.cs | 5 +++-- .../ExportProviderBuilder.cs | 19 ++++++++++++---- .../Program.cs | 2 +- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs index fb8cd3e84a46a..d5e193d7a8edf 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs @@ -7,6 +7,7 @@ using Microsoft.VisualStudio.Composition; using Microsoft.VisualStudio.LanguageServer.Protocol; using Nerdbank.Streams; +using Roslyn.Utilities; using StreamJsonRpc; using Xunit.Abstractions; @@ -33,7 +34,8 @@ protected sealed class TestLspServer : IAsyncDisposable public static async Task CreateAsync(ClientCapabilities clientCapabilities, ILogger logger) { - var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + var loggerFactory = new LoggerFactory(SpecializedCollections.SingletonEnumerable(new TestLoggerProvider(logger))); + var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(loggerFactory); var testLspServer = new TestLspServer(exportProvider, logger); var initializeResponse = await testLspServer.ExecuteRequestAsync(Methods.InitializeName, new InitializeParams { Capabilities = clientCapabilities }, CancellationToken.None); Assert.NotNull(initializeResponse?.Capabilities); @@ -91,4 +93,22 @@ public async ValueTask DisposeAsync() _clientRpc.Dispose(); } } + + private class TestLoggerProvider : ILoggerProvider + { + private readonly ILogger _testLogger; + public TestLoggerProvider(ILogger testLogger) + { + _testLogger = testLogger; + } + + public ILogger CreateLogger(string categoryName) + { + return _testLogger; + } + + public void Dispose() + { + } + } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs index 974c077b76be2..857daab709b31 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/WorkspaceProjectFactoryServiceTests.cs @@ -14,8 +14,9 @@ public class WorkspaceProjectFactoryServiceTests [Fact] public async Task CreateProjectAndBatch() { - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); - exportProvider.GetExportedValue().SetFactory(new LoggerFactory()); + var loggerFactory = new LoggerFactory(); + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(loggerFactory); + exportProvider.GetExportedValue().SetFactory(loggerFactory); var workspaceFactory = exportProvider.GetExportedValue(); var workspaceProjectFactoryServiceInstance = (WorkspaceProjectFactoryService)exportProvider diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index a0ecbc0478ec3..6ad0cd06916ea 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -13,8 +13,10 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal sealed class ExportProviderBuilder { - public static async Task CreateExportProviderAsync() + public static async Task CreateExportProviderAsync(ILoggerFactory loggerFactory) { + var logger = loggerFactory.CreateLogger(); + var baseDirectory = AppContext.BaseDirectory; var resolver = new Resolver(new CustomExportAssemblyLoader(baseDirectory)); @@ -48,7 +50,7 @@ public static async Task CreateExportProviderAsync() var config = CompositionConfiguration.Create(catalog); // Verify we only have expected errors. - ThrowOnUnexpectedErrors(config); + ThrowOnUnexpectedErrors(config, logger); // Prepare an ExportProvider factory based on this graph. var exportProviderFactory = config.CreateExportProviderFactory(); @@ -60,7 +62,7 @@ public static async Task CreateExportProviderAsync() return exportProvider; } - private static void ThrowOnUnexpectedErrors(CompositionConfiguration configuration) + private static void ThrowOnUnexpectedErrors(CompositionConfiguration configuration, ILogger logger) { // Verify that we have exactly the MEF errors that we expect. If we have less or more this needs to be updated to assert the expected behavior. // Currently we are expecting the following: @@ -74,7 +76,16 @@ private static void ThrowOnUnexpectedErrors(CompositionConfiguration configurati var expectedErroredParts = new string[] { "PythiaSignatureHelpProvider" }; if (erroredParts.Count() != expectedErroredParts.Length || !erroredParts.All(part => expectedErroredParts.Contains(part))) { - configuration.ThrowOnErrors(); + try + { + configuration.ThrowOnErrors(); + } + catch (CompositionFailedException ex) + { + // The ToString for the composition failed exception doesn't output a nice set of errors by default, so log it separately here. + logger.LogError($"Encountered errors in the MEF composition:{Environment.NewLine}{ex.ErrorsAsString}"); + throw; + } } } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 7b1da5f7b0986..66bc361effcef 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -63,7 +63,7 @@ static async Task RunAsync(bool launchDebugger, string? brokeredServicePipeName, } } - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(); + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(loggerFactory); // Immediately set the logger factory, so that way it'll be available for the rest of the composition exportProvider.GetExportedValue().SetFactory(loggerFactory); From 8e1a8fc12becc8d89adaf0d1c0362437206c4b69 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 3 May 2023 13:44:14 +1000 Subject: [PATCH 224/261] Even more PR feedback --- .../HostWorkspace/RazorInitializeHandler.cs | 1 - .../RazorWorkspaceListenerInitializer.cs | 22 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs index cadb438da8ea6..41bfb872c4c61 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorInitializeHandler.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Composition; -using System.Runtime.Serialization; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CommonLanguageServerProtocol.Framework; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs index cb26c0a5149b7..a5db86545ae6d 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorWorkspaceListenerInitializer.cs @@ -2,13 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Collections.Immutable; using System.Composition; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.Extensions.Logging; @@ -23,11 +17,13 @@ internal sealed class RazorWorkspaceListenerInitializer private const string _projectRazorJsonFileName = "project.razor.vscode.json"; private readonly ILogger _logger; - private readonly HashSet _projectIdWithDynamicFiles = new(); - private readonly object _initializeGate = new(); private readonly Lazy _workspaceFactory; private readonly ILoggerFactory _loggerFactory; + // Locks all access to _razorWorkspaceListener and _projectIdWithDynamicFiles + private readonly object _initializeGate = new(); + private readonly HashSet _projectIdWithDynamicFiles = new(); + private RazorWorkspaceListener? _razorWorkspaceListener; [ImportingConstructor] @@ -42,6 +38,7 @@ public RazorWorkspaceListenerInitializer(Lazy wo internal void Initialize() { + ProjectId[] projectsToInitialize; lock (_initializeGate) { // Only initialize once @@ -53,16 +50,17 @@ internal void Initialize() _logger.LogTrace("Initializing the Razor workspace listener"); _razorWorkspaceListener = new RazorWorkspaceListener(_loggerFactory); _razorWorkspaceListener.EnsureInitialized(_workspaceFactory.Value.Workspace, _projectRazorJsonFileName); + + projectsToInitialize = _projectIdWithDynamicFiles.ToArray(); + // May as well clear out the collection, it will never get used again anyway. + _projectIdWithDynamicFiles.Clear(); } - foreach (var projectId in _projectIdWithDynamicFiles) + foreach (var projectId in projectsToInitialize) { _logger.LogTrace("{projectId} notifying a dynamic file for the first time", projectId); _razorWorkspaceListener.NotifyDynamicFile(projectId); } - - // May as well clear out the collection, it will never get used again anyway. - _projectIdWithDynamicFiles.Clear(); } internal void NotifyDynamicFile(ProjectId projectId) From ffff7a3e34f8bf38df31580c9f07e36ab8754e14 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 3 May 2023 13:45:51 +1000 Subject: [PATCH 225/261] May as well use the same Razor that will ship with VS --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 82646727a2bd3..255d790f8f242 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -78,7 +78,7 @@ $(RefOnlyMicrosoftBuildPackagesVersion) 6.0.0-preview.0.15 17.2.31 - 7.0.0-preview.23229.1 + 7.0.0-preview.23251.2 + true + false + false + false + $(CommonExtensionInstallationRoot) + $(LanguageServicesExtensionInstallationFolder)\Core + + + + Microsoft.CodeAnalysis.LanguageServices + + + + .\ + core + + + + + e_sqlite3.dll + PreserveNewest + true + false + + + + + + diff --git a/src/VisualStudio/Setup.ServiceHub/Directory.Build.targets b/src/VisualStudio/Setup.ServiceHub/Directory.Build.targets index f3be81af53814..80144b8f4d738 100644 --- a/src/VisualStudio/Setup.ServiceHub/Directory.Build.targets +++ b/src/VisualStudio/Setup.ServiceHub/Directory.Build.targets @@ -1,6 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/src/VisualStudio/Setup.ServiceHub/arm64/Roslyn.VisualStudio.ServiceHub.Setup.arm64.csproj b/src/VisualStudio/Setup.ServiceHub/arm64/Roslyn.VisualStudio.ServiceHub.Setup.arm64.csproj new file mode 100644 index 0000000000000..3f632b59bb9f9 --- /dev/null +++ b/src/VisualStudio/Setup.ServiceHub/arm64/Roslyn.VisualStudio.ServiceHub.Setup.arm64.csproj @@ -0,0 +1,27 @@ + + + + + Library + net472 + arm64 + + + + ServiceHubARM64 + + true + false + PublishProjectOutputGroup + + false + + false + + + + + Designer + + + diff --git a/src/VisualStudio/Setup.ServiceHub/arm64/source.extension.vsixmanifest b/src/VisualStudio/Setup.ServiceHub/arm64/source.extension.vsixmanifest new file mode 100644 index 0000000000000..aca276e84b870 --- /dev/null +++ b/src/VisualStudio/Setup.ServiceHub/arm64/source.extension.vsixmanifest @@ -0,0 +1,33 @@ + + + + + Roslyn Services for .NET ServiceHub Host + Roslyn Services for .NET ServiceHub Host + Microsoft.CodeAnalysis.VisualStudio.ServiceHub.Setup.arm64 + EULA.rtf + true + + + + arm64 + + + arm64 + + + arm64 + + + arm64 + + + + + + + + + + + diff --git a/src/VisualStudio/Setup.ServiceHub/x64/Roslyn.VisualStudio.ServiceHub.Setup.x64.csproj b/src/VisualStudio/Setup.ServiceHub/x64/Roslyn.VisualStudio.ServiceHub.Setup.x64.csproj index 5c3e5e165765f..91e99dca1c9f0 100644 --- a/src/VisualStudio/Setup.ServiceHub/x64/Roslyn.VisualStudio.ServiceHub.Setup.x64.csproj +++ b/src/VisualStudio/Setup.ServiceHub/x64/Roslyn.VisualStudio.ServiceHub.Setup.x64.csproj @@ -1,29 +1,10 @@  - Library net472 - false - - - true x64 - false - false - false - $(CommonExtensionInstallationRoot) - $(LanguageServicesExtensionInstallationFolder)\Core - - - Microsoft.CodeAnalysis.LanguageServices - - - - .\ - core @@ -37,28 +18,10 @@ false - - - - e_sqlite3.dll - PreserveNewest - true - false - Designer - - - - - - - - - - diff --git a/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj b/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj index abcdf267870a5..22e9dafc12cc9 100644 --- a/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj +++ b/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj @@ -228,6 +228,13 @@ false + + VisualStudioServiceHubSetupX64 + false + + + false + XamlVisualStudio BuiltProjectOutputGroup;SatelliteDllsProjectOutputGroup diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/CoreComponents.Shared.targets b/src/Workspaces/Remote/ServiceHub.CoreComponents/CoreComponents.Shared.targets index 53d1f3d8b547c..793cc289f10ec 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/CoreComponents.Shared.targets +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/CoreComponents.Shared.targets @@ -3,6 +3,11 @@ + + false + true $(MicrosoftNetCoreAppPackagesVersion) diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/arm64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.arm64.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/arm64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.arm64.csproj new file mode 100644 index 0000000000000..2ce6770dae226 --- /dev/null +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/arm64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.arm64.csproj @@ -0,0 +1,22 @@ + + + + + Exe + net6.0 + arm64 + + $(MicrosoftNetCoreAppPackagesVersion) + $(MicrosoftNetCoreAppPackagesVersion) + + + + + + + <_RuntimeLibrariesPath>$(PkgMicrosoft_NETCore_App_Runtime_win-arm64)\runtimes\win-arm64\ + <_WinRuntimeLibrariesPath>$(PkgMicrosoft_WindowsDesktop_App_Runtime_win-arm64)\runtimes\win-arm64\ + + + + \ No newline at end of file diff --git a/src/Workspaces/Remote/ServiceHub.CoreComponents/x64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.x64.csproj b/src/Workspaces/Remote/ServiceHub.CoreComponents/x64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.x64.csproj index 5921c46f14642..b867949e303a1 100644 --- a/src/Workspaces/Remote/ServiceHub.CoreComponents/x64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.x64.csproj +++ b/src/Workspaces/Remote/ServiceHub.CoreComponents/x64/Microsoft.CodeAnalysis.Remote.ServiceHub.CoreComponents.x64.csproj @@ -4,11 +4,6 @@ Exe net6.0 - - - false x64 $(MicrosoftNetCoreAppPackagesVersion) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs index 68fa8d01fbfec..38fad72af3ed2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs @@ -726,12 +726,12 @@ private static bool VerifyGetAsyncEnumerator(IMethodSymbol getAsyncEnumerator) /// /// Returns true for symbols whose name starts with an underscore and - /// are optionally followed by an integer, such as '_', '_1', '_2', etc. + /// are optionally followed by an integer or other underscores, such as '_', '_1', '_2', '__', '___', etc. /// These are treated as special discard symbol names. /// public static bool IsSymbolWithSpecialDiscardName(this ISymbol symbol) => symbol.Name.StartsWith("_") && - (symbol.Name.Length == 1 || uint.TryParse(symbol.Name[1..], out _)); + (symbol.Name.Length == 1 || uint.TryParse(symbol.Name[1..], out _) || symbol.Name.All(n => n.Equals('_'))); /// /// Returns , if the symbol is marked with the . diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.BasicBlockAnalysisData.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.BasicBlockAnalysisData.cs index 45c98a5326b28..72f17fc65156d 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.BasicBlockAnalysisData.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.BasicBlockAnalysisData.cs @@ -237,7 +237,10 @@ private static void AddEntries(Dictionary> re #if NET values.EnsureCapacity(values.Count + operations.Count); #endif - values.AddRange(operations); + + // Enumerate explicitly, instead of calling AddRange, to avoid unnecessary expensive IEnumerator allocation. + foreach (var operation in operations) + values.Add(operation); } } } From fb200c75895c599d2cd98deec131feec86a96736 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 May 2023 17:24:04 +1000 Subject: [PATCH 233/261] Don't use a FileTextLoader for dynamic files, which don't exist on disk --- .../HostWorkspace/LanguageServerWorkspace.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs index f53aa75270518..f425fe2b3d4f2 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs @@ -91,8 +91,16 @@ internal override ValueTask TryOnDocumentClosedAsync(DocumentId documentId, Canc { // TODO(cyrusn): This only works for normal documents currently. We'll have to rethink how things work // in the world if we ever support additionalfiles/editorconfig in our language server. - var filePath = w.CurrentSolution.GetDocument(documentId)?.FilePath; - if (filePath != null) + var document = w.CurrentSolution.GetDocument(documentId); + + // We assume that dynamic files don't exist on disk, so if we were to use the FileTextLoader we'd effectively + // be emptying out the document. This assumption is only valid for dynamic files because we further assume they're + // not user editable, and hence can't have "unsaved" changes that are expected to go away on close. + if (document is + { + DocumentState.Attributes.DesignTimeOnly: false, + FilePath: { } filePath + }) { var loader = this.ProjectSystemProjectFactory.CreateFileTextLoader(filePath); this.OnDocumentClosedEx(documentId, loader, requireDocumentPresentAndOpen: false); From 92117365fa74cb2eb25c904875bc324a2126d638 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 May 2023 11:55:42 +0000 Subject: [PATCH 234/261] Apply suggestions from code review --- .../HostWorkspace/LanguageServerWorkspace.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs index f425fe2b3d4f2..9edfe4efddae9 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs @@ -92,7 +92,7 @@ internal override ValueTask TryOnDocumentClosedAsync(DocumentId documentId, Canc // TODO(cyrusn): This only works for normal documents currently. We'll have to rethink how things work // in the world if we ever support additionalfiles/editorconfig in our language server. var document = w.CurrentSolution.GetDocument(documentId); - + // We assume that dynamic files don't exist on disk, so if we were to use the FileTextLoader we'd effectively // be emptying out the document. This assumption is only valid for dynamic files because we further assume they're // not user editable, and hence can't have "unsaved" changes that are expected to go away on close. From f8cdd296a52b7dcecafebaef11c5977066f577df Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Fri, 12 May 2023 14:39:31 -0700 Subject: [PATCH 235/261] Rename file to match the class within --- ...keredServiceTraceLogger.cs => BrokeredServiceTraceListener.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/{BrokeredServiceTraceLogger.cs => BrokeredServiceTraceListener.cs} (100%) diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceListener.cs similarity index 100% rename from src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceLogger.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/BrokeredServiceTraceListener.cs From 22a73891fa619b19e834dba36eea0905f2736082 Mon Sep 17 00:00:00 2001 From: "Andrew Hall (METAL)" Date: Tue, 16 May 2023 00:00:01 +0000 Subject: [PATCH 236/261] Merged PR 31216: Upgrade the telemetry package and include more required runtime dependencies The telemetry package update includes needed fixes for csdevkit. The runtime dependencies were being silently swallowed as exceptions and could cause telemetry to not function appropriately. --- eng/Versions.props | 3 ++- ...soft.VisualStudio.LanguageServices.DevKit.csproj | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 7eeb7bc81a43b..10ff219881f8f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -189,7 +189,7 @@ $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) - 17.7.8 + 17.7.17 8.0.0.0-alpha $(VisualStudioEditorPackagesVersion) $(VisualStudioEditorPackagesVersion) @@ -200,6 +200,7 @@ $(MicrosoftVisualStudioThreadingPackagesVersion) $(MicrosoftVisualStudioThreadingPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) + 16.3.42 17.6.11 4.0.0 4.0.0 diff --git a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj index ac312c598aea0..681e017e4dd7e 100644 --- a/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj +++ b/src/VisualStudio/DevKit/Impl/Microsoft.VisualStudio.LanguageServices.DevKit.csproj @@ -37,6 +37,16 @@ Runtime dependency is required to pack in npm. Do not remove GeneratePathProperty="True" as it defines PkgMicrosoft_VisualStudio_RemoteControl --> + + + + + + @@ -59,6 +69,9 @@ + + + From b7dabc726e8a1dd987867f3ba63dac9e5003a5d3 Mon Sep 17 00:00:00 2001 From: Arun Chander Kalyanasamy Date: Tue, 16 May 2023 00:14:07 +0000 Subject: [PATCH 237/261] Merged PR 31260: Merge main --- docs/Breaking API Changes.md | 17 ++ .../AbstractUpgradeProjectCodeFixProvider.cs | 2 + .../SymbolDisplayVisitor.Members.cs | 2 +- .../Symbols/Source/SourceNamedTypeSymbol.cs | 48 ++-- .../Source/SourceOrdinaryMethodSymbol.cs | 57 +++-- .../Source/SourceOrdinaryMethodSymbolBase.cs | 12 +- .../Symbols/Source/TypeParameterInfo.cs | 37 +++ .../SynthesizedRecordOrdinaryMethod.cs | 2 +- .../Diagnostics/DiagnosticAnalyzerTests.cs | 2 +- ...iverTests_Attributes_FullyQualifiedName.cs | 14 +- ...eratorDriverTests_Attributes_SimpleName.cs | 8 +- .../SourceGeneration/StateTableTests.cs | 4 +- .../SymbolDisplay/SymbolDisplayTests.cs | 67 ++++++ .../CompilationWithAnalyzersTests.cs | 2 +- .../DiagnosticLocalizationTests.cs | 8 +- .../DiagnosticAnalyzer/AnalyzerDriver.cs | 21 +- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 143 ++++-------- .../DiagnosticAnalyzer/AnalyzerManager.cs | 80 ++++--- .../CompilationWithAnalyzers.cs | 36 ++- .../IncrementalStepRunReason.cs | 4 +- .../SourceGeneration/Nodes/NodeStateTable.cs | 2 +- .../SymbolDisplayCompilerInternalOptions.cs | 5 +- .../SymbolDisplay/SymbolDisplayFormat.cs | 8 +- .../Core/Diagnostics/DiagnosticExtensions.cs | 1 + .../Diagnostics/DiagnosticAnalyzerTests.vb | 14 +- ...iverTests_Attributes_FullyQualifiedName.vb | 14 +- ...eratorDriverTests_Attributes_SimpleName.vb | 4 +- .../EditAndContinue/SyntaxComparerTests.cs | 52 ++--- .../NavigateTo/NavigateToSearcherTests.cs | 2 +- .../DefaultNavigateToPreviewService.cs | 6 +- .../NavigateTo/INavigateToPreviewService.cs | 4 +- .../NavigateTo/NavigateToItemDisplay.cs | 28 ++- .../Core.Wpf/Peek/PeekableItemSource.cs | 2 +- .../DefinitionContextTracker.cs | 2 +- .../Core/NavigateTo/NavigateToHelpers.cs | 2 +- .../CrossLanguageCodeDefinitionWindowTests.vb | 6 +- .../EditAndContinue/SyntaxComparerTests.vb | 27 ++- .../EditAndContinue/SyntaxComparer.cs | 30 +-- ...ddConstructorParametersFromMembersTests.cs | 66 +++--- .../GenerateConstructorFromMembersTests.cs | 6 +- .../VSTypeScriptNavigableItemWrapper.cs | 4 +- .../NavigateTo/RoslynNavigateToItem.cs | 77 +++--- .../Portable/Navigation/INavigableItem.cs | 53 ++++- ...ItemFactory.SymbolLocationNavigableItem.cs | 26 ++- .../Extensions/ProtocolConversions.cs | 4 +- .../AbstractGoToDefinitionHandler.cs | 5 +- .../Symbols/WorkspaceSymbolsHandler.cs | 4 +- .../EditAndContinue/SyntaxComparer.vb | 31 +-- .../Navigation/InternalFSharpNavigableItem.cs | 6 + .../OmniSharpFindDefinitionService.cs | 5 +- .../OmniSharpNavigateToSearchService.cs | 10 +- .../DocumentOutline/DocumentOutlineTests.cs | 60 ++++- .../DocumentOutlineTestsBase.cs | 2 +- src/VisualStudio/Core/Def/Commands.vsct | 86 +++++++ .../DocumentOutlineOptionsStorage.cs | 2 + .../DocumentOutline/DocumentOutlineStrings.cs | 19 +- .../DocumentOutline/DocumentOutlineView.xaml | 62 +---- .../DocumentOutlineView.xaml.cs | 220 +++++++++++++++--- .../DocumentOutlineViewModel_Utilities.cs | 7 +- src/VisualStudio/Core/Def/Guids.cs | 3 + .../Core/Def/ID.RoslynCommands.cs | 9 + ...ctLanguageService`2.VsCodeWindowManager.cs | 4 +- .../VisualStudioNavigateToPreviewService.cs | 7 +- .../Def/Options/VisualStudioOptionStorage.cs | 1 + .../Core/Def/Progression/GraphBuilder.cs | 6 +- .../ProgressionNavigateToSearchCallback.cs | 2 +- .../Core/Def/ServicesVSResources.resx | 15 -- .../Core/Def/xlf/Commands.vsct.cs.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.de.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.es.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.fr.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.it.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.ja.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.ko.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.pl.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.pt-BR.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.ru.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.tr.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.zh-Hans.xlf | 110 +++++++++ .../Core/Def/xlf/Commands.vsct.zh-Hant.xlf | 110 +++++++++ .../Core/Def/xlf/ServicesVSResources.cs.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.de.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.es.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.fr.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.it.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.ja.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.ko.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.pl.xlf | 25 -- .../Def/xlf/ServicesVSResources.pt-BR.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.ru.xlf | 25 -- .../Core/Def/xlf/ServicesVSResources.tr.xlf | 25 -- .../Def/xlf/ServicesVSResources.zh-Hans.xlf | 25 -- .../Def/xlf/ServicesVSResources.zh-Hant.xlf | 25 -- .../Definitions/GoToDefinitionHandler.cs | 4 +- .../Differencing/LongestCommonSubsequence.cs | 46 ++-- .../Differencing/LongestCommonSubstring.cs | 4 +- .../Core/Extensions/ISolutionExtensions.cs | 4 +- 97 files changed, 2469 insertions(+), 921 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterInfo.cs diff --git a/docs/Breaking API Changes.md b/docs/Breaking API Changes.md index 994d2b6dd8d3a..4b2782b0c79f3 100644 --- a/docs/Breaking API Changes.md +++ b/docs/Breaking API Changes.md @@ -71,3 +71,20 @@ All property setters now throw an exception. The `Workspace` and `DocumentId` parameters of `TextLoader.LoadTextAndVersionAsync(Workspace, DocumentId, CancellationToken)` are deprecated. The method now receives `null` `Workspace` and `DocumentId`. + +# Version 4.5.0 + +`SymbolDisplayFormat.CSharpErrorMessageFormat` and `CSharpShortErrorMessageFormat` now include parameter names by default if used on a standalone `IParameterSymbol`. +For example, parameter `p` in `void M(ref int p)` was previously formatted as `"ref int"` and now it is formatted as `"ref int p"`. + +# Version 4.7.0 + +### `SymbolDisplayFormat` includes parameter name when invoked on `IParameterSymbol` + +All `SymbolDisplayFormat`s (predefined and user-created) now include parameter names by default if used on a standalone `IParameterSymbol` for consistency with predefined formats (see the breaking change for version 4.5.0 above). + +### Changed `IncrementalStepRunReason` when a modified input produced a new output + +`IncrementalGeneratorRunStep.Outputs` previously contained `IncrementalStepRunReason.Modified` as `Reason` +when the input to the step was modified in a way that produced a new output. +Now the reason will be reported more accurately as `IncrementalStepRunReason.New`. \ No newline at end of file diff --git a/src/Analyzers/Core/CodeFixes/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs index c61bc4d74224f..bf940d14b87e4 100644 --- a/src/Analyzers/Core/CodeFixes/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs @@ -122,6 +122,8 @@ protected override Task> ComputePreviewOperatio internal class ProjectOptionsChangeAction : SolutionChangeAction { + public override ImmutableArray Tags => RequiresNonDocumentChangeTags; + private ProjectOptionsChangeAction(string title, Func> createChangedSolution) : base(title, createChangedSolution, equivalenceKey: null, priority: CodeActionPriority.Default, createdFromFactoryMethod: true) { diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs index da9b6816450a8..9aeeb3524e212 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs @@ -798,7 +798,7 @@ public override void VisitParameter(IParameterSymbol symbol) var includeType = format.ParameterOptions.IncludesOption(SymbolDisplayParameterOptions.IncludeType); var includeName = symbol.Name.Length != 0 && (format.ParameterOptions.IncludesOption(SymbolDisplayParameterOptions.IncludeName) || - (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.IncludeParameterNameIfStandalone) && builder.Count == 0)); + (!format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.ExcludeParameterNameIfStandalone) && builder.Count == 0)); var includeBrackets = format.ParameterOptions.IncludesOption(SymbolDisplayParameterOptions.IncludeOptionalBrackets); var includeDefaultValue = format.ParameterOptions.IncludesOption(SymbolDisplayParameterOptions.IncludeDefaultValue) && format.ParameterOptions.IncludesOption(SymbolDisplayParameterOptions.IncludeName) && diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index 01950c5021b6d..e3029c48fcb94 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -23,19 +23,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols // That is, for a generic type C this is the instance type C. internal sealed partial class SourceNamedTypeSymbol : SourceMemberContainerTypeSymbol, IAttributeTargetSymbol { - private ImmutableArray _lazyTypeParameters; - - /// - /// A collection of type parameter constraint types, populated when - /// constraint types for the first type parameter are requested. - /// - private ImmutableArray> _lazyTypeParameterConstraintTypes; - - /// - /// A collection of type parameter constraint kinds, populated when - /// constraint kinds for the first type parameter are requested. - /// - private ImmutableArray _lazyTypeParameterConstraintKinds; + private readonly TypeParameterInfo _typeParameterInfo; private CustomAttributesBag _lazyCustomAttributesBag; @@ -104,6 +92,10 @@ internal SourceNamedTypeSymbol(NamespaceOrTypeSymbol containingSymbol, MergedTyp // Nested types are never unified. _lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.False; } + + _typeParameterInfo = declaration.Arity == 0 + ? TypeParameterInfo.Empty + : new TypeParameterInfo(); } protected override NamedTypeSymbol WithTupleDataCore(TupleExtraData newData) @@ -277,21 +269,22 @@ internal ImmutableArray GetTypeParameterConstraintTypes(int private ImmutableArray> GetTypeParameterConstraintTypes() { - var constraintTypes = _lazyTypeParameterConstraintTypes; - if (constraintTypes.IsDefault) + if (_typeParameterInfo.LazyTypeParameterConstraintTypes.IsDefault) { GetTypeParameterConstraintKinds(); var diagnostics = BindingDiagnosticBag.GetInstance(); - if (ImmutableInterlocked.InterlockedInitialize(ref _lazyTypeParameterConstraintTypes, MakeTypeParameterConstraintTypes(diagnostics))) + if (ImmutableInterlocked.InterlockedInitialize( + ref _typeParameterInfo.LazyTypeParameterConstraintTypes, + MakeTypeParameterConstraintTypes(diagnostics))) { this.AddDeclarationDiagnostics(diagnostics); } diagnostics.Free(); - constraintTypes = _lazyTypeParameterConstraintTypes; } - return constraintTypes; + Debug.Assert(!_typeParameterInfo.LazyTypeParameterConstraintTypes.IsDefault); + return _typeParameterInfo.LazyTypeParameterConstraintTypes; } /// @@ -305,14 +298,15 @@ internal TypeParameterConstraintKind GetTypeParameterConstraintKind(int ordinal) private ImmutableArray GetTypeParameterConstraintKinds() { - var constraintKinds = _lazyTypeParameterConstraintKinds; - if (constraintKinds.IsDefault) + if (_typeParameterInfo.LazyTypeParameterConstraintKinds.IsDefault) { - ImmutableInterlocked.InterlockedInitialize(ref _lazyTypeParameterConstraintKinds, MakeTypeParameterConstraintKinds()); - constraintKinds = _lazyTypeParameterConstraintKinds; + ImmutableInterlocked.InterlockedInitialize( + ref _typeParameterInfo.LazyTypeParameterConstraintKinds, + MakeTypeParameterConstraintKinds()); } - return constraintKinds; + Debug.Assert(!_typeParameterInfo.LazyTypeParameterConstraintKinds.IsDefault); + return _typeParameterInfo.LazyTypeParameterConstraintKinds; } private ImmutableArray> MakeTypeParameterConstraintTypes(BindingDiagnosticBag diagnostics) @@ -749,10 +743,12 @@ public override ImmutableArray TypeParameters { get { - if (_lazyTypeParameters.IsDefault) + if (_typeParameterInfo.LazyTypeParameters.IsDefault) { var diagnostics = BindingDiagnosticBag.GetInstance(); - if (ImmutableInterlocked.InterlockedInitialize(ref _lazyTypeParameters, MakeTypeParameters(diagnostics))) + if (ImmutableInterlocked.InterlockedInitialize( + ref _typeParameterInfo.LazyTypeParameters, + MakeTypeParameters(diagnostics))) { AddDeclarationDiagnostics(diagnostics); } @@ -760,7 +756,7 @@ public override ImmutableArray TypeParameters diagnostics.Free(); } - return _lazyTypeParameters; + return _typeParameterInfo.LazyTypeParameters; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 55127be6d829e..b619030b5f6ec 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -4,7 +4,6 @@ #nullable disable -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Globalization; @@ -25,19 +24,7 @@ internal sealed class SourceOrdinaryMethodSymbol : SourceOrdinaryMethodSymbolBas private readonly RefKind _refKind; private bool _lazyIsVararg; - /// - /// A collection of type parameter constraint types, populated when - /// constraint types for the first type parameter is requested. - /// Initialized in two steps. Hold a copy if accessing during initialization. - /// - private ImmutableArray> _lazyTypeParameterConstraintTypes; - - /// - /// A collection of type parameter constraint kinds, populated when - /// constraint kinds for the first type parameter is requested. - /// Initialized in two steps. Hold a copy if accessing during initialization. - /// - private ImmutableArray _lazyTypeParameterConstraintKinds; + private readonly TypeParameterInfo _typeParameterInfo; /// /// If this symbol represents a partial method definition or implementation part, its other part (if any). @@ -92,6 +79,13 @@ internal sealed class SourceOrdinaryMethodSymbol : SourceOrdinaryMethodSymbolBas { Debug.Assert(diagnostics.DiagnosticBag is object); + // Compute the type parameters. If empty (the common case), directly point at the singleton to reduce the + // amount of pointers-to-arrays this type needs to store. + var typeParameters = MakeTypeParameters(syntax, diagnostics); + _typeParameterInfo = typeParameters.IsEmpty + ? TypeParameterInfo.Empty + : new TypeParameterInfo { LazyTypeParameters = typeParameters }; + _explicitInterfaceType = explicitInterfaceType; bool hasBlockBody = syntax.Body != null; @@ -105,17 +99,12 @@ internal sealed class SourceOrdinaryMethodSymbol : SourceOrdinaryMethodSymbolBas syntax.Body, syntax.ExpressionBody, syntax, diagnostics); } - protected override ImmutableArray MakeTypeParameters(CSharpSyntaxNode node, BindingDiagnosticBag diagnostics) + public override ImmutableArray TypeParameters { - var syntax = (MethodDeclarationSyntax)node; - if (syntax.Arity == 0) - { - ReportErrorIfHasConstraints(syntax.ConstraintClauses, diagnostics.DiagnosticBag); - return ImmutableArray.Empty; - } - else + get { - return MakeTypeParameters(syntax, diagnostics); + Debug.Assert(!_typeParameterInfo.LazyTypeParameters.IsDefault); + return _typeParameterInfo.LazyTypeParameters; } } @@ -308,7 +297,7 @@ protected override void CompleteAsyncMethodChecksBetweenStartAndFinish() public override ImmutableArray> GetTypeParameterConstraintTypes() { - if (_lazyTypeParameterConstraintTypes.IsDefault) + if (_typeParameterInfo.LazyTypeParameterConstraintTypes.IsDefault) { GetTypeParameterConstraintKinds(); @@ -324,19 +313,21 @@ public override ImmutableArray> GetTypeParam syntax.TypeParameterList, syntax.ConstraintClauses, diagnostics); - if (ImmutableInterlocked.InterlockedInitialize(ref _lazyTypeParameterConstraintTypes, constraints)) + if (ImmutableInterlocked.InterlockedInitialize( + ref _typeParameterInfo.LazyTypeParameterConstraintTypes, + constraints)) { this.AddDeclarationDiagnostics(diagnostics); } diagnostics.Free(); } - return _lazyTypeParameterConstraintTypes; + return _typeParameterInfo.LazyTypeParameterConstraintTypes; } public override ImmutableArray GetTypeParameterConstraintKinds() { - if (_lazyTypeParameterConstraintKinds.IsDefault) + if (_typeParameterInfo.LazyTypeParameterConstraintKinds.IsDefault) { var syntax = GetSyntax(); var withTypeParametersBinder = @@ -349,10 +340,12 @@ public override ImmutableArray GetTypeParameterCons syntax.TypeParameterList, syntax.ConstraintClauses); - ImmutableInterlocked.InterlockedInitialize(ref _lazyTypeParameterConstraintKinds, constraints); + ImmutableInterlocked.InterlockedInitialize( + ref _typeParameterInfo.LazyTypeParameterConstraintKinds, + constraints); } - return _lazyTypeParameterConstraintKinds; + return _typeParameterInfo.LazyTypeParameterConstraintKinds; } public override bool IsVararg @@ -530,6 +523,12 @@ protected override DeclarationModifiers MakeDeclarationModifiers(DeclarationModi private ImmutableArray MakeTypeParameters(MethodDeclarationSyntax syntax, BindingDiagnosticBag diagnostics) { + if (syntax.Arity == 0) + { + ReportErrorIfHasConstraints(syntax.ConstraintClauses, diagnostics.DiagnosticBag); + return ImmutableArray.Empty; + } + Debug.Assert(syntax.TypeParameterList != null); MessageID.IDS_FeatureGenerics.CheckFeatureAvailability(diagnostics, syntax.TypeParameterList.LessThanToken); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs index 9769624caabcf..2eaef04464ab7 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbolBase.cs @@ -23,7 +23,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols /// internal abstract class SourceOrdinaryMethodSymbolBase : SourceOrdinaryMethodOrUserDefinedOperatorSymbol { - private readonly ImmutableArray _typeParameters; private readonly string _name; protected SourceOrdinaryMethodSymbolBase( @@ -62,8 +61,6 @@ internal abstract class SourceOrdinaryMethodSymbolBase : SourceOrdinaryMethodOrU this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod: isExtensionMethod, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers); - _typeParameters = MakeTypeParameters(syntax, diagnostics); - CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics); if (hasBody) @@ -74,8 +71,6 @@ internal abstract class SourceOrdinaryMethodSymbolBase : SourceOrdinaryMethodOrU ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation: isExplicitInterfaceImplementation, diagnostics, location); } - protected abstract ImmutableArray MakeTypeParameters(CSharpSyntaxNode node, BindingDiagnosticBag diagnostics); - #nullable enable protected override void MethodChecks(BindingDiagnosticBag diagnostics) { @@ -89,7 +84,7 @@ protected override void MethodChecks(BindingDiagnosticBag diagnostics) { for (int i = 0; i < declaredConstraints.Length; i++) { - var typeParameter = _typeParameters[i]; + var typeParameter = this.TypeParameters[i]; ErrorCode report; switch (declaredConstraints[i].Constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.Default)) @@ -171,10 +166,7 @@ private void CompleteAsyncMethodChecks(BindingDiagnosticBag diagnosticsOpt, Canc protected abstract void CompleteAsyncMethodChecksBetweenStartAndFinish(); - public override ImmutableArray TypeParameters - { - get { return _typeParameters; } - } + public abstract override ImmutableArray TypeParameters { get; } public abstract override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterInfo.cs b/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterInfo.cs new file mode 100644 index 0000000000000..7a91009a35962 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterInfo.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + /// + /// Wrapper around type-parameter/constraints/constraint-kind info. We wrap this information (instead of inlining + /// directly within type/method symbols) as most types/methods are not generic. As such, all those non-generic + /// types can point at the singleton sentinel value, and avoid two pointers of overhead. + /// + internal sealed class TypeParameterInfo + { + public ImmutableArray LazyTypeParameters; + + /// + /// A collection of type parameter constraint types, populated when + /// constraint types for the first type parameter are requested. + /// + public ImmutableArray> LazyTypeParameterConstraintTypes; + + /// + /// A collection of type parameter constraint kinds, populated when + /// constraint kinds for the first type parameter are requested. + /// + public ImmutableArray LazyTypeParameterConstraintKinds; + + public static readonly TypeParameterInfo Empty = new TypeParameterInfo + { + LazyTypeParameters = ImmutableArray.Empty, + LazyTypeParameterConstraintTypes = ImmutableArray>.Empty, + LazyTypeParameterConstraintKinds = ImmutableArray.Empty, + }; + } +} diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs index c497dbc226869..f063d89aa6ca9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordOrdinaryMethod.cs @@ -39,7 +39,7 @@ protected SynthesizedRecordOrdinaryMethod(SourceMemberContainerTypeSymbol contai internal sealed override LexicalSortKey GetLexicalSortKey() => LexicalSortKey.GetSynthesizedMemberKey(_memberOffset); - protected sealed override ImmutableArray MakeTypeParameters(CSharpSyntaxNode node, BindingDiagnosticBag diagnostics) => ImmutableArray.Empty; + public sealed override ImmutableArray TypeParameters => ImmutableArray.Empty; public sealed override ImmutableArray> GetTypeParameterConstraintTypes() => ImmutableArray>.Empty; diff --git a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs index 190a4b1ed0ee9..530819e1264fb 100644 --- a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs @@ -516,7 +516,7 @@ public override void Initialize(AnalysisContext context) } } - [Fact] + [Fact, Obsolete(message: "IsDiagnosticAnalyzerSuppressed is an obsolete public API")] public void TestDisabledAnalyzers() { var fullyDisabledAnalyzer = new FullyDisabledAnalyzer(); diff --git a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.cs b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.cs index 4f88c6eab55c7..c04f59b7d7121 100644 --- a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.cs +++ b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.cs @@ -1493,7 +1493,7 @@ class XAttribute : System.Attribute Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps["result_ForAttributeInternal"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps["compilationAndGroupedNodes_ForAttributeWithMetadataName"].Single().Outputs.Single().Reason); - Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps["result_ForAttributeWithMetadataName"].Single().Outputs.Single().Reason); + Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["result_ForAttributeWithMetadataName"].Single().Outputs.Single().Reason); } [Fact] @@ -1544,8 +1544,8 @@ class XAttribute : System.Attribute t => Assert.Equal(IncrementalStepRunReason.Cached, t.Reason)); Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps["compilationAndGroupedNodes_ForAttributeWithMetadataName"].Single().Outputs.Single().Reason); Assert.Collection(runResult.TrackedSteps["result_ForAttributeWithMetadataName"].Single().Outputs, - t => Assert.Equal(IncrementalStepRunReason.Modified, t.Reason), - t => Assert.Equal(IncrementalStepRunReason.Modified, t.Reason)); + t => Assert.Equal(IncrementalStepRunReason.New, t.Reason), + t => Assert.Equal(IncrementalStepRunReason.New, t.Reason)); } [Fact] @@ -1601,8 +1601,8 @@ class XAttribute : System.Attribute s => Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason), s => Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason)); Assert.Collection(runResult.TrackedSteps["result_ForAttributeWithMetadataName"], - s => Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason), - s => Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason)); + s => Assert.Equal(IncrementalStepRunReason.New, s.Outputs.Single().Reason), + s => Assert.Equal(IncrementalStepRunReason.New, s.Outputs.Single().Reason)); } [Fact] @@ -1651,7 +1651,7 @@ class XAttribute : System.Attribute Assert.Equal(IncrementalStepRunReason.Unchanged, runResult.TrackedSteps["collectedGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps["compilationGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps["allUpGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); - Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps["compilationUnit_ForAttribute"].Single().Outputs.Single().Reason); + Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["compilationUnit_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["result_ForAttributeInternal"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["compilationAndGroupedNodes_ForAttributeWithMetadataName"].Single().Outputs.Single().Reason); @@ -1700,7 +1700,7 @@ class C { } Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps["compilationGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps["allUpGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Collection(runResult.TrackedSteps["compilationUnit_ForAttribute"].Single().Outputs, - o => Assert.Equal(IncrementalStepRunReason.Modified, o.Reason)); + o => Assert.Equal(IncrementalStepRunReason.New, o.Reason)); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["result_ForAttributeInternal"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["compilationAndGroupedNodes_ForAttributeWithMetadataName"].Single().Outputs.Single().Reason); diff --git a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.cs b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.cs index 2f94d34906029..eddd65200a21e 100644 --- a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.cs +++ b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.cs @@ -1218,7 +1218,7 @@ class C { } Assert.Collection(runResult.TrackedSteps["compilationUnit_ForAttribute"].Single().Outputs, o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), - o => Assert.Equal(IncrementalStepRunReason.Modified, o.Reason)); + o => Assert.Equal(IncrementalStepRunReason.New, o.Reason)); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["result_ForAttribute"].Single().Outputs.Single().Reason); @@ -1410,7 +1410,7 @@ class C { } Assert.Collection(runResult.TrackedSteps["compilationUnit_ForAttribute"].Single().Outputs, o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), - o => Assert.Equal(IncrementalStepRunReason.Modified, o.Reason)); + o => Assert.Equal(IncrementalStepRunReason.New, o.Reason)); Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["result_ForAttribute"].Single().Outputs.Single().Reason); @@ -1452,7 +1452,7 @@ class C { } Assert.Collection(runResult.TrackedSteps["compilationUnit_ForAttribute"].Single().Outputs, o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), - o => Assert.Equal(IncrementalStepRunReason.Modified, o.Reason)); + o => Assert.Equal(IncrementalStepRunReason.New, o.Reason)); Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"].Single().Outputs.Single().Reason); Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps["result_ForAttribute"].Single().Outputs.Single().Reason); @@ -1553,7 +1553,7 @@ class D { }")))); o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), o => Assert.Equal(IncrementalStepRunReason.Unchanged, o.Reason), - o => Assert.Equal(IncrementalStepRunReason.Modified, o.Reason)); + o => Assert.Equal(IncrementalStepRunReason.New, o.Reason)); Assert.Collection(runResult.TrackedSteps["compilationUnitAndGlobalAliases_ForAttribute"], s => Assert.Equal(IncrementalStepRunReason.Cached, s.Outputs.Single().Reason), s => Assert.Equal(IncrementalStepRunReason.New, s.Outputs.Single().Reason)); diff --git a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs index e48ce6a86981d..bb73064c78ebc 100644 --- a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs @@ -1006,7 +1006,7 @@ public void Modified_Entry_Adding_Outputs_Records_Added_Step_State() values = ImmutableArray.Create(1, 2, 3); - // second time we'll see that the "Input" step is modified, but the outputs of the "SelectMany" step are modified. + // second time we'll see that the "Input" step is modified, but the outputs of the "SelectMany" step are new. dstBuilder = GetBuilder(dstBuilder.ToImmutable(), trackIncrementalGeneratorSteps: true); var table = dstBuilder.GetLatestStateTableForNode(transformNode); @@ -1018,7 +1018,7 @@ public void Modified_Entry_Adding_Outputs_Records_Added_Step_State() Assert.All(step.Outputs, output => { - Assert.Equal(IncrementalStepRunReason.Modified, output.Reason); + Assert.Equal(IncrementalStepRunReason.New, output.Reason); }); } diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index b4738476b29b4..9da6044f90402 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -8222,6 +8222,73 @@ void M(string s!!) SymbolDisplayPartKind.Punctuation); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67464")] + public void Parameter_Standalone() + { + var source = """ + class C + { + void M(ref int p) { } + } + """; + var comp = CreateCompilation(source); + var methodSymbol = comp.GetMember("C.M").GetPublicSymbol(); + var parameterSymbol = methodSymbol.Parameters.Single(); + + var format = s_memberSignatureDisplayFormat.RemoveParameterOptions(SymbolDisplayParameterOptions.IncludeName); + + Verify(methodSymbol.ToDisplayParts(format), "void C.M(ref int)", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation); + + Verify(methodSymbol.ToDisplayParts(SymbolDisplayFormat.CSharpErrorMessageFormat), "C.M(ref int)", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation); + + Verify(methodSymbol.ToDisplayParts(SymbolDisplayFormat.CSharpErrorMessageNoParameterNamesFormat), "C.M(ref int)", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation); + + Verify(parameterSymbol.ToDisplayParts(format), "ref int p", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName); + + Verify(parameterSymbol.ToDisplayParts(SymbolDisplayFormat.CSharpErrorMessageFormat), "ref int p", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName); + + Verify(parameterSymbol.ToDisplayParts(SymbolDisplayFormat.CSharpErrorMessageNoParameterNamesFormat), "ref int", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword); + } + [Fact] public void TestRequiredProperty() { diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs index 764b282bf749b..995ddab41fdf6 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs @@ -69,7 +69,7 @@ public void GetAnalyzerTelemetry() Assert.Equal(0, analyzerTelemetry.SymbolActionsCount); } - [Fact] + [Fact, Obsolete(message: "IsDiagnosticAnalyzerSuppressed is an obsolete public API")] public void TestIsDiagnosticAnalyzerSuppressedWithExceptionInSupportedDiagnostics() { // Verify IsDiagnosticAnalyzerSuppressed does not throw an exception when 'onAnalyzerException' is null. diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs index b231f852494f1..9764d5519b5cf 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs @@ -303,7 +303,13 @@ private static void TestDescriptorIsExceptionSafeCore(DiagnosticDescriptor descr Action onAnalyzerException = (ex, a, diag, ct) => exceptionDiagnostics.Add(diag); var analyzerManager = new AnalyzerManager(analyzer); - var analyzerExecutor = AnalyzerExecutor.CreateForSupportedDiagnostics(onAnalyzerException, analyzerManager); + var compilation = CSharp.CSharpCompilation.Create("test"); + var analyzerExecutor = AnalyzerExecutor.Create(compilation, AnalyzerOptions.Empty, + addNonCategorizedDiagnostic: (_, _) => { }, onAnalyzerException, analyzerExceptionFilter: null, + isCompilerAnalyzer: _ => false, analyzerManager, shouldSkipAnalysisOnGeneratedCode: _ => false, + shouldSuppressGeneratedCodeDiagnostic: (_, _, _, _) => false, isGeneratedCodeLocation: (_, _, _) => false, + isAnalyzerSuppressedForTree: (_, _, _, _) => false, getAnalyzerGate: _ => null, + getSemanticModel: tree => compilation.GetSemanticModel(tree, ignoreAccessibility: true)); var descriptors = analyzerManager.GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, CancellationToken.None); Assert.Equal(1, descriptors.Length); diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index 732e7a27078ca..25e378800c6ae 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using ReferenceEqualityComparer = Roslyn.Utilities.ReferenceEqualityComparer; @@ -1031,10 +1032,14 @@ void executeSuppressionActions(IEnumerable reportedDiagnostics, bool { foreach (var suppressor in suppressors) { - var task = Task.Run( - () => AnalyzerExecutor.ExecuteSuppressionAction(suppressor, getSuppressableDiagnostics(suppressor), cancellationToken), - cancellationToken); - tasks.Add(task); + var suppressableDiagnostics = getSuppressableDiagnostics(suppressor); + if (!suppressableDiagnostics.IsEmpty) + { + var task = Task.Run( + () => AnalyzerExecutor.ExecuteSuppressionAction(suppressor, suppressableDiagnostics, cancellationToken), + cancellationToken); + tasks.Add(task); + } } Task.WaitAll(tasks.ToArray(), cancellationToken); @@ -1062,7 +1067,7 @@ ImmutableArray getSuppressableDiagnostics(DiagnosticSuppressor suppr return ImmutableArray.Empty; } - var builder = ArrayBuilder.GetInstance(); + using var builder = TemporaryArray.Empty; foreach (var diagnostic in reportedDiagnostics) { if (supportedSuppressions.Contains(s => s.SuppressedDiagnosticId == diagnostic.Id)) @@ -1071,7 +1076,7 @@ ImmutableArray getSuppressableDiagnostics(DiagnosticSuppressor suppr } } - return builder.ToImmutableAndFree(); + return builder.ToImmutableAndClear(); } } @@ -2287,14 +2292,14 @@ internal async Task GetAnalyzerActionCountsAsync(Diagnosti CompilationOptions options, AnalyzerManager analyzerManager, AnalyzerExecutor analyzerExecutor, - AnalysisScope? analysisScope, + AnalysisScope analysisScope, SeverityFilter severityFilter, CancellationToken cancellationToken) { return analyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, s_IsCompilerAnalyzerFunc, analyzerExecutor, analysisScope, severityFilter, cancellationToken); } - private static bool IsCompilerAnalyzer(DiagnosticAnalyzer analyzer) => analyzer is CompilerDiagnosticAnalyzer; + internal static bool IsCompilerAnalyzer(DiagnosticAnalyzer analyzer) => analyzer is CompilerDiagnosticAnalyzer; public void Dispose() { diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index da35ff8171563..c5f9321f2543b 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -31,22 +31,19 @@ internal partial class AnalyzerExecutor internal const string AnalyzerExceptionDiagnosticId = "AD0001"; internal const string AnalyzerDriverExceptionDiagnosticId = "AD0002"; - private readonly Compilation? _compilation; - private readonly AnalyzerOptions? _analyzerOptions; private readonly Action? _addNonCategorizedDiagnostic; private readonly Action? _addCategorizedLocalDiagnostic; private readonly Action? _addCategorizedNonLocalDiagnostic; private readonly Action? _addSuppression; - private readonly Action _onAnalyzerException; private readonly Func? _analyzerExceptionFilter; private readonly AnalyzerManager _analyzerManager; - private readonly Func? _isCompilerAnalyzer; - private readonly Func? _getAnalyzerGate; - private readonly Func? _getSemanticModel; + private readonly Func _isCompilerAnalyzer; + private readonly Func _getAnalyzerGate; + private readonly Func _getSemanticModel; private readonly Func _shouldSkipAnalysisOnGeneratedCode; private readonly Func _shouldSuppressGeneratedCodeDiagnostic; private readonly Func _isGeneratedCodeLocation; - private readonly Func? _isAnalyzerSuppressedForTree; + private readonly Func _isAnalyzerSuppressedForTree; /// /// The values in this map convert to using . @@ -63,7 +60,6 @@ internal partial class AnalyzerExecutor private bool IsAnalyzerSuppressedForTree(DiagnosticAnalyzer analyzer, SyntaxTree tree, CancellationToken cancellationToken) { - Debug.Assert(_isAnalyzerSuppressedForTree != null); return _isAnalyzerSuppressedForTree(analyzer, tree, Compilation.Options.SyntaxTreeOptionsProvider, cancellationToken); } @@ -129,62 +125,29 @@ private bool IsAnalyzerSuppressedForTree(DiagnosticAnalyzer analyzer, SyntaxTree addSuppression); } - /// - /// Creates to fetch . - /// - /// - /// Optional delegate which is invoked when an analyzer throws an exception. - /// Delegate can do custom tasks such as report the given analyzer exception diagnostic, report a non-fatal watson for the exception, etc. - /// - /// Analyzer manager to fetch supported diagnostics. - public static AnalyzerExecutor CreateForSupportedDiagnostics( - Action? onAnalyzerException, - AnalyzerManager analyzerManager) - { - onAnalyzerException ??= (ex, analyzer, diagnostic, cancellationToken) => { }; - return new AnalyzerExecutor( - compilation: null, - analyzerOptions: null, - addNonCategorizedDiagnosticOpt: null, - isCompilerAnalyzer: null, - shouldSkipAnalysisOnGeneratedCode: _ => false, - shouldSuppressGeneratedCodeDiagnostic: (diagnostic, analyzer, compilation, ct) => false, - isGeneratedCodeLocation: (_1, _2, _3) => false, - isAnalyzerSuppressedForTree: null, - getAnalyzerGate: null, - getSemanticModel: null, - onAnalyzerException: onAnalyzerException, - analyzerExceptionFilter: null, - analyzerManager: analyzerManager, - analyzerExecutionTimeMap: null, - addCategorizedLocalDiagnostic: null, - addCategorizedNonLocalDiagnostic: null, - addSuppression: null); - } - private AnalyzerExecutor( - Compilation? compilation, - AnalyzerOptions? analyzerOptions, + Compilation compilation, + AnalyzerOptions analyzerOptions, Action? addNonCategorizedDiagnosticOpt, Action onAnalyzerException, Func? analyzerExceptionFilter, - Func? isCompilerAnalyzer, + Func isCompilerAnalyzer, AnalyzerManager analyzerManager, Func shouldSkipAnalysisOnGeneratedCode, Func shouldSuppressGeneratedCodeDiagnostic, Func isGeneratedCodeLocation, - Func? isAnalyzerSuppressedForTree, - Func? getAnalyzerGate, - Func? getSemanticModel, + Func isAnalyzerSuppressedForTree, + Func getAnalyzerGate, + Func getSemanticModel, ConcurrentDictionary>? analyzerExecutionTimeMap, Action? addCategorizedLocalDiagnostic, Action? addCategorizedNonLocalDiagnostic, Action? addSuppression) { - _compilation = compilation; - _analyzerOptions = analyzerOptions; + Compilation = compilation; + AnalyzerOptions = analyzerOptions; _addNonCategorizedDiagnostic = addNonCategorizedDiagnosticOpt; - _onAnalyzerException = onAnalyzerException; + OnAnalyzerException = onAnalyzerException; _analyzerExceptionFilter = analyzerExceptionFilter; _isCompilerAnalyzer = isCompilerAnalyzer; _analyzerManager = analyzerManager; @@ -202,33 +165,11 @@ private bool IsAnalyzerSuppressedForTree(DiagnosticAnalyzer analyzer, SyntaxTree _compilationAnalysisValueProviderFactory = new CompilationAnalysisValueProviderFactory(); } - internal bool TryGetCompilationAndAnalyzerOptions( - [NotNullWhen(true)] out Compilation? compilation, - [NotNullWhen(true)] out AnalyzerOptions? analyzerOptions) - { - (compilation, analyzerOptions) = (_compilation, _analyzerOptions); - return compilation != null && analyzerOptions != null; - } + internal Compilation Compilation { get; } - internal Compilation Compilation - { - get - { - Debug.Assert(_compilation != null); - return _compilation; - } - } + internal AnalyzerOptions AnalyzerOptions { get; } - internal AnalyzerOptions AnalyzerOptions - { - get - { - Debug.Assert(_analyzerOptions != null); - return _analyzerOptions; - } - } - - internal Action OnAnalyzerException => _onAnalyzerException; + internal Action OnAnalyzerException { get; } internal ImmutableDictionary AnalyzerExecutionTimes { get @@ -335,7 +276,6 @@ public void ExecuteCompilationStartActions(ImmutableArray reportedDiagnostics, CancellationToken cancellationToken) { Debug.Assert(_addSuppression != null); - Debug.Assert(_getSemanticModel != null); if (reportedDiagnostics.IsEmpty) { @@ -1178,7 +1118,7 @@ internal void ExecuteAndCatchIfThrows(DiagnosticAnalyzer analyzer, Action< timer = SharedStopwatch.StartNew(); } - var gate = _getAnalyzerGate?.Invoke(analyzer); + var gate = _getAnalyzerGate(analyzer); if (gate != null) { lock (gate) @@ -1209,34 +1149,51 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A cancellationToken.ThrowIfCancellationRequested(); analyze(argument); } - catch (Exception e) when (ExceptionFilter(e, cancellationToken)) + catch (Exception ex) when (HandleAnalyzerException(ex, analyzer, info, OnAnalyzerException, _analyzerExceptionFilter, cancellationToken)) { - // Diagnostic for analyzer exception. - var diagnostic = CreateAnalyzerExceptionDiagnostic(analyzer, e, info); - try - { - _onAnalyzerException(e, analyzer, diagnostic, cancellationToken); - } - catch (Exception) - { - // Ignore exceptions from exception handlers. - } } } - internal bool ExceptionFilter(Exception ex, CancellationToken cancellationToken) + internal static bool HandleAnalyzerException( + Exception exception, + DiagnosticAnalyzer analyzer, + AnalysisContextInfo? info, + Action onAnalyzerException, + Func? analyzerExceptionFilter, + CancellationToken cancellationToken) { - if ((ex as OperationCanceledException)?.CancellationToken == cancellationToken) + if (!ExceptionFilter(exception, analyzerExceptionFilter, cancellationToken)) { return false; } - if (_analyzerExceptionFilter != null) + // Diagnostic for analyzer exception. + var diagnostic = CreateAnalyzerExceptionDiagnostic(analyzer, exception, info); + try + { + onAnalyzerException(exception, analyzer, diagnostic, cancellationToken); + } + catch (Exception) { - return _analyzerExceptionFilter(ex); + // Ignore exceptions from exception handlers. } return true; + + static bool ExceptionFilter(Exception ex, Func? analyzerExceptionFilter, CancellationToken cancellationToken) + { + if ((ex as OperationCanceledException)?.CancellationToken == cancellationToken) + { + return false; + } + + if (analyzerExceptionFilter != null) + { + return analyzerExceptionFilter(ex); + } + + return true; + } } internal static Diagnostic CreateAnalyzerExceptionDiagnostic(DiagnosticAnalyzer analyzer, Exception e, AnalysisContextInfo? info = null) @@ -1359,8 +1316,6 @@ internal static bool AreEquivalentAnalyzerExceptionDiagnostics(Diagnostic except private bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, CancellationToken cancellationToken) { - Debug.Assert(_isCompilerAnalyzer != null); - if (diagnostic is DiagnosticWithInfo) { // Compiler diagnostic diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs index d862b6e362b51..d8ed74f140798 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs @@ -293,9 +293,52 @@ internal bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diag CompilationOptions options, Func isCompilerAnalyzer, AnalyzerExecutor analyzerExecutor, - AnalysisScope? analysisScope, + AnalysisScope analysisScope, SeverityFilter severityFilter, CancellationToken cancellationToken) + { + Func> getSupportedDiagnosticDescriptors = + analyzer => GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, cancellationToken); + Func> getSupportedSuppressionDescriptors = + suppressor => GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor, cancellationToken); + + return IsDiagnosticAnalyzerSuppressed(analyzer, options, isCompilerAnalyzer, severityFilter, + isEnabledWithAnalyzerConfigOptions, getSupportedDiagnosticDescriptors, getSupportedSuppressionDescriptors, cancellationToken); + + bool isEnabledWithAnalyzerConfigOptions(DiagnosticDescriptor descriptor) + { + if (analyzerExecutor.Compilation.Options.SyntaxTreeOptionsProvider is { } treeOptions) + { + foreach (var tree in analysisScope.SyntaxTrees) + { + // Check if diagnostic is enabled by SyntaxTree.DiagnosticOptions or Bulk configuration from AnalyzerConfigOptions. + if (treeOptions.TryGetDiagnosticValue(tree, descriptor.Id, cancellationToken, out var configuredValue) || + analyzerExecutor.AnalyzerOptions.TryGetSeverityFromBulkConfiguration(tree, analyzerExecutor.Compilation, descriptor, cancellationToken, out configuredValue)) + { + if (configuredValue != ReportDiagnostic.Suppress && !severityFilter.Contains(configuredValue)) + { + return true; + } + } + } + } + + return false; + } + } + + /// + /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options. + /// + internal static bool IsDiagnosticAnalyzerSuppressed( + DiagnosticAnalyzer analyzer, + CompilationOptions options, + Func isCompilerAnalyzer, + SeverityFilter severityFilter, + Func isEnabledWithAnalyzerConfigOptions, + Func> getSupportedDiagnosticDescriptors, + Func> getSupportedSuppressionDescriptors, + CancellationToken cancellationToken) { if (isCompilerAnalyzer(analyzer)) { @@ -303,9 +346,8 @@ internal bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diag return false; } - var supportedDiagnostics = GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, cancellationToken); + var supportedDiagnostics = getSupportedDiagnosticDescriptors(analyzer); var diagnosticOptions = options.SpecificDiagnosticOptions; - analyzerExecutor.TryGetCompilationAndAnalyzerOptions(out var compilation, out var analyzerOptions); foreach (var diag in supportedDiagnostics) { @@ -349,7 +391,7 @@ internal bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diag // Editorconfig user settings override compilation wide settings. if (isSuppressed && - isEnabledWithAnalyzerConfigOptions(diag, severityFilter, compilation, analyzerOptions, analysisScope, cancellationToken)) + isEnabledWithAnalyzerConfigOptions(diag)) { isSuppressed = false; } @@ -362,7 +404,7 @@ internal bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diag if (analyzer is DiagnosticSuppressor suppressor) { - foreach (var suppressionDescriptor in GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor, cancellationToken)) + foreach (var suppressionDescriptor in getSupportedSuppressionDescriptors(suppressor)) { if (!suppressionDescriptor.IsDisabled(options)) { @@ -372,34 +414,6 @@ internal bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diag } return true; - - static bool isEnabledWithAnalyzerConfigOptions( - DiagnosticDescriptor descriptor, - SeverityFilter severityFilter, - Compilation? compilation, - AnalyzerOptions? analyzerOptions, - AnalysisScope? analysisScope, - CancellationToken cancellationToken) - { - if (compilation != null && compilation.Options.SyntaxTreeOptionsProvider is { } treeOptions) - { - var trees = analysisScope?.SyntaxTrees ?? compilation.SyntaxTrees; - foreach (var tree in trees) - { - // Check if diagnostic is enabled by SyntaxTree.DiagnosticOptions or Bulk configuration from AnalyzerConfigOptions. - if (treeOptions.TryGetDiagnosticValue(tree, descriptor.Id, cancellationToken, out var configuredValue) || - analyzerOptions.TryGetSeverityFromBulkConfiguration(tree, compilation, descriptor, cancellationToken, out configuredValue)) - { - if (configuredValue != ReportDiagnostic.Suppress && !severityFilter.Contains(configuredValue)) - { - return true; - } - } - } - } - - return false; - } } internal static bool HasCompilerOrNotConfigurableTag(ImmutableArray customTags) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs index 561bb9abe738b..e61d6a21f6d54 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs @@ -1132,7 +1132,8 @@ private static IEnumerable GetEffectiveDiagnosticsImpl(ImmutableArra /// /// Optional delegate which is invoked when an analyzer throws an exception. /// Delegate can do custom tasks such as report the given analyzer exception diagnostic, report a non-fatal watson for the exception, etc. - /// + /// + [Obsolete("This API is no longer supported. See https://github.com/dotnet/roslyn/issues/67592 for details")] public static bool IsDiagnosticAnalyzerSuppressed( DiagnosticAnalyzer analyzer, CompilationOptions options, @@ -1147,10 +1148,35 @@ private static IEnumerable GetEffectiveDiagnosticsImpl(ImmutableArra var analyzerManager = new AnalyzerManager(analyzer); - Action? wrappedOnAnalyzerException = - onAnalyzerException == null ? null : (ex, analyzer, diagnostic, _) => onAnalyzerException(ex, analyzer, diagnostic); - var analyzerExecutor = AnalyzerExecutor.CreateForSupportedDiagnostics(wrappedOnAnalyzerException, analyzerManager); - return AnalyzerDriver.IsDiagnosticAnalyzerSuppressed(analyzer, options, analyzerManager, analyzerExecutor, analysisScope: null, severityFilter: SeverityFilter.None, CancellationToken.None); + Action wrappedOnAnalyzerException = + (ex, analyzer, diagnostic, _) => onAnalyzerException?.Invoke(ex, analyzer, diagnostic); + + Func> getSupportedDiagnosticDescriptors = analyzer => + { + try + { + return analyzer.SupportedDiagnostics; + } + catch (Exception ex) when (AnalyzerExecutor.HandleAnalyzerException(ex, analyzer, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None)) + { + return ImmutableArray.Empty; + } + }; + + Func> getSupportedSuppressionDescriptors = suppressor => + { + try + { + return suppressor.SupportedSuppressions; + } + catch (Exception ex) when (AnalyzerExecutor.HandleAnalyzerException(ex, suppressor, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None)) + { + return ImmutableArray.Empty; + } + }; + + return AnalyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, IsCompilerAnalyzer, severityFilter: SeverityFilter.None, + isEnabledWithAnalyzerConfigOptions: _ => false, getSupportedDiagnosticDescriptors, getSupportedSuppressionDescriptors, CancellationToken.None); ; } /// diff --git a/src/Compilers/Core/Portable/SourceGeneration/IncrementalStepRunReason.cs b/src/Compilers/Core/Portable/SourceGeneration/IncrementalStepRunReason.cs index 926df4eae7ed7..96aef636c3a6c 100644 --- a/src/Compilers/Core/Portable/SourceGeneration/IncrementalStepRunReason.cs +++ b/src/Compilers/Core/Portable/SourceGeneration/IncrementalStepRunReason.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis public enum IncrementalStepRunReason { /// - /// The output of this step is a new output produced from a new input. + /// The input to this step was added or modified from a previous run, and it produced a new output. /// New, @@ -30,7 +30,7 @@ public enum IncrementalStepRunReason Cached, /// - /// The input that this output is generated from was removed from the input step's outputs, so this value will be removed from the output step results. + /// The input to this step was removed or modified from a previous run, and the output it used to generate is no longer present. /// Removed } diff --git a/src/Compilers/Core/Portable/SourceGeneration/Nodes/NodeStateTable.cs b/src/Compilers/Core/Portable/SourceGeneration/Nodes/NodeStateTable.cs index 6adccae5bbd00..20822a5f7261d 100644 --- a/src/Compilers/Core/Portable/SourceGeneration/Nodes/NodeStateTable.cs +++ b/src/Compilers/Core/Portable/SourceGeneration/Nodes/NodeStateTable.cs @@ -423,7 +423,7 @@ private static IncrementalStepRunReason AsStepState(EntryState inputState, Entry (EntryState.Cached, EntryState.Cached) => IncrementalStepRunReason.Cached, (EntryState.Removed, EntryState.Removed) => IncrementalStepRunReason.Removed, (EntryState.Modified, EntryState.Removed) => IncrementalStepRunReason.Removed, - (EntryState.Modified, EntryState.Added) => IncrementalStepRunReason.Modified, + (EntryState.Modified, EntryState.Added) => IncrementalStepRunReason.New, _ => throw ExceptionUtilities.UnexpectedValue((inputState, outputState)) }; } diff --git a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayCompilerInternalOptions.cs b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayCompilerInternalOptions.cs index b5b970f3cf55c..eea505665d8d8 100644 --- a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayCompilerInternalOptions.cs +++ b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayCompilerInternalOptions.cs @@ -69,10 +69,9 @@ internal enum SymbolDisplayCompilerInternalOptions IncludeContainingFileForFileTypes = 1 << 8, /// - /// Equivalent to - /// but only if the parameter is displayed on its own + /// Does not include parameter name if the parameter is displayed on its own /// (i.e., not as part of a method, delegate, or indexer). /// - IncludeParameterNameIfStandalone = 1 << 9, + ExcludeParameterNameIfStandalone = 1 << 9, } } diff --git a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs index a5ed1dc05cdb2..7ff86cd4e5360 100644 --- a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs +++ b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs @@ -32,11 +32,10 @@ public class SymbolDisplayFormat SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.UseAsterisksInMultiDimensionalArrays | SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName | - SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier, - compilerInternalOptions: SymbolDisplayCompilerInternalOptions.IncludeParameterNameIfStandalone); + SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier); internal static SymbolDisplayFormat CSharpErrorMessageNoParameterNamesFormat { get; } = CSharpErrorMessageFormat - .RemoveCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeParameterNameIfStandalone); + .AddCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.ExcludeParameterNameIfStandalone); /// /// Formats a symbol description as in a C# compiler short error message. @@ -59,8 +58,7 @@ public class SymbolDisplayFormat SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.UseAsterisksInMultiDimensionalArrays | SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName | - SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier, - compilerInternalOptions: SymbolDisplayCompilerInternalOptions.IncludeParameterNameIfStandalone); + SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier); /// /// Formats a symbol description as in a Visual Basic compiler error message. diff --git a/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs b/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs index 0211f83eddabc..75b0e0e80653f 100644 --- a/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs +++ b/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs @@ -344,6 +344,7 @@ public static IEnumerable GetEffectiveDiagnostics(this Compilation c /// /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options. /// + [Obsolete("This API is no longer supported. See https://github.com/dotnet/roslyn/issues/67592 for details")] public static bool IsDiagnosticAnalyzerSuppressed(this DiagnosticAnalyzer analyzer, CompilationOptions options) { return CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, options); diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb index ea1f007c6443d..24721c44d70ba 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb @@ -241,22 +241,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics End Sub End Class - + Public Sub TestDisabledAnalyzers() - Dim FullyDisabledAnalyzer = New FullyDisabledAnalyzer() - Dim PartiallyDisabledAnalyzer = New PartiallyDisabledAnalyzer() + Dim fullyDisabledAnalyzer = New FullyDisabledAnalyzer() + Dim partiallyDisabledAnalyzer = New PartiallyDisabledAnalyzer() Dim options = TestOptions.ReleaseDll - Assert.True(FullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) - Assert.False(PartiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + Assert.False(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() specificDiagOptions.Add(FullyDisabledAnalyzer.desc1.Id, ReportDiagnostic.Warn) specificDiagOptions.Add(PartiallyDisabledAnalyzer.desc2.Id, ReportDiagnostic.Suppress) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) - Assert.False(FullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) - Assert.True(PartiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + Assert.False(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + Assert.True(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) End Sub Public Class ModuleStatementAnalyzer diff --git a/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.vb b/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.vb index 89d00c4a1f098..4a2fed5d7a313 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_FullyQualifiedName.vb @@ -1058,7 +1058,7 @@ end class Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("compilationUnitAndGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("result_ForAttributeInternal").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps("compilationAndGroupedNodes_ForAttributeWithMetadataName").Single().Outputs.Single().Reason) - Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps("result_ForAttributeWithMetadataName").Single().Outputs.Single().Reason) + Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("result_ForAttributeWithMetadataName").Single().Outputs.Single().Reason) End Sub @@ -1110,8 +1110,8 @@ end class")))) Sub(t) Assert.Equal(IncrementalStepRunReason.Cached, t.Reason)) Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps("compilationAndGroupedNodes_ForAttributeWithMetadataName").Single().Outputs.Single().Reason) Assert.Collection(runResult.TrackedSteps("result_ForAttributeWithMetadataName").Single().Outputs, - Sub(t) Assert.Equal(IncrementalStepRunReason.Modified, t.Reason), - Sub(t) Assert.Equal(IncrementalStepRunReason.Modified, t.Reason)) + Sub(t) Assert.Equal(IncrementalStepRunReason.New, t.Reason), + Sub(t) Assert.Equal(IncrementalStepRunReason.New, t.Reason)) End Sub @@ -1168,8 +1168,8 @@ Sub(_step) Assert.Collection(_step.Outputs, Sub(t) Assert.True(IsClassStatementW Sub(s) Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason), Sub(s) Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason)) Assert.Collection(runResult.TrackedSteps("result_ForAttributeWithMetadataName"), - Sub(s) Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason), - Sub(s) Assert.Equal(IncrementalStepRunReason.Modified, s.Outputs.Single().Reason)) + Sub(s) Assert.Equal(IncrementalStepRunReason.New, s.Outputs.Single().Reason), + Sub(s) Assert.Equal(IncrementalStepRunReason.New, s.Outputs.Single().Reason)) End Sub @@ -1220,7 +1220,7 @@ end class Assert.Equal(IncrementalStepRunReason.Unchanged, runResult.TrackedSteps("collectedGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("compilationGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("allUpGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) - Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps("compilationUnit_ForAttribute").Single().Outputs.Single().Reason) + Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationUnit_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationUnitAndGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("result_ForAttributeInternal").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationAndGroupedNodes_ForAttributeWithMetadataName").Single().Outputs.Single().Reason) @@ -1271,7 +1271,7 @@ end class Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("compilationGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("allUpGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Collection(runResult.TrackedSteps("compilationUnit_ForAttribute").Single().Outputs, - Sub(o) Assert.Equal(IncrementalStepRunReason.Modified, o.Reason)) + Sub(o) Assert.Equal(IncrementalStepRunReason.New, o.Reason)) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationUnitAndGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("result_ForAttributeInternal").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationAndGroupedNodes_ForAttributeWithMetadataName").Single().Outputs.Single().Reason) diff --git a/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.vb b/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.vb index d89ef1d11a824..bb1840e773129 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/SourceGeneration/GeneratorDriverTests_Attributes_SimpleName.vb @@ -1258,7 +1258,7 @@ end class Assert.Equal(IncrementalStepRunReason.Unchanged, runResult.TrackedSteps("collectedGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.Cached, runResult.TrackedSteps("allUpGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) - Assert.Equal(IncrementalStepRunReason.Modified, runResult.TrackedSteps("compilationUnit_ForAttribute").Single().Outputs.Single().Reason) + Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationUnit_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("compilationUnitAndGlobalAliases_ForAttribute").Single().Outputs.Single().Reason) Assert.Equal(IncrementalStepRunReason.New, runResult.TrackedSteps("result_ForAttribute").Single().Outputs.Single().Reason) @@ -1465,7 +1465,7 @@ end class")))) Assert.Collection(runResult.TrackedSteps("compilationUnit_ForAttribute").Single().Outputs, Sub(_step) Assert.Equal(IncrementalStepRunReason.Unchanged, _step.Reason), - Sub(_step) Assert.Equal(IncrementalStepRunReason.Modified, _step.Reason)) + Sub(_step) Assert.Equal(IncrementalStepRunReason.New, _step.Reason)) Assert.Collection(runResult.TrackedSteps("compilationUnitAndGlobalAliases_ForAttribute"), Sub(_step) Assert.Equal(IncrementalStepRunReason.Cached, _step.Outputs.Single().Reason), Sub(_step) Assert.Equal(IncrementalStepRunReason.New, _step.Outputs.Single().Reason)) diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs index 95f06a78ca88c..8f291d192482c 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Immutable; +using System.Linq; using Microsoft.CodeAnalysis.Differencing; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -84,7 +85,7 @@ public void GetSequenceEdits4() } [Fact] - public void ComputeDistance1() + public void ComputeDistance_Nodes() { var distance = SyntaxComparer.ComputeDistance( new[] { MakeLiteral(0), MakeLiteral(1), MakeLiteral(2) }, @@ -94,17 +95,7 @@ public void ComputeDistance1() } [Fact] - public void ComputeDistance2() - { - var distance = SyntaxComparer.ComputeDistance( - ImmutableArray.Create(MakeLiteral(0), MakeLiteral(1), MakeLiteral(2)), - ImmutableArray.Create(MakeLiteral(1), MakeLiteral(3))); - - Assert.Equal(0.67, Math.Round(distance, 2)); - } - - [Fact] - public void ComputeDistance3() + public void ComputeDistance_Tokens() { var distance = SyntaxComparer.ComputeDistance( new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword) }, @@ -113,16 +104,6 @@ public void ComputeDistance3() Assert.Equal(0.33, Math.Round(distance, 2)); } - [Fact] - public void ComputeDistance4() - { - var distance = SyntaxComparer.ComputeDistance( - ImmutableArray.Create(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)), - ImmutableArray.Create(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword))); - - Assert.Equal(0.33, Math.Round(distance, 2)); - } - [Fact] public void ComputeDistance_Token() { @@ -141,18 +122,6 @@ public void ComputeDistance_Node() public void ComputeDistance_Null() { var distance = SyntaxComparer.ComputeDistance( - default, - ImmutableArray.Create(SyntaxFactory.Token(SyntaxKind.StaticKeyword))); - - Assert.Equal(1, Math.Round(distance, 2)); - - distance = SyntaxComparer.ComputeDistance( - default, - ImmutableArray.Create(MakeLiteral(0))); - - Assert.Equal(1, Math.Round(distance, 2)); - - distance = SyntaxComparer.ComputeDistance( null, Array.Empty()); @@ -176,5 +145,20 @@ public void ComputeDistance_Null() Assert.Equal(0, Math.Round(distance, 2)); } + + [Fact] + public void ComputeDistance_LongSequences() + { + var t1 = SyntaxFactory.Token(SyntaxKind.PublicKeyword); + var t2 = SyntaxFactory.Token(SyntaxKind.PrivateKeyword); + var t3 = SyntaxFactory.Token(SyntaxKind.ProtectedKeyword); + + var distance = SyntaxComparer.ComputeDistance( + Enumerable.Range(0, 10000).Select(i => i < 2000 ? t1 : t2), + Enumerable.Range(0, 10000).Select(i => i < 2000 ? t1 : t3)); + + // long sequences are indistinguishable if they have common prefix shorter then threshold: + Assert.Equal(0, distance); + } } } diff --git a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToSearcherTests.cs b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToSearcherTests.cs index 3ee2eb013e056..09100345c3016 100644 --- a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToSearcherTests.cs +++ b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToSearcherTests.cs @@ -270,7 +270,7 @@ public TestNavigateToSearchResult(TestWorkspace workspace, TextSpan sourceSpan) _sourceSpan = sourceSpan; } - public Document Document => _workspace.CurrentSolution.Projects.Single().Documents.Single(); + public INavigableItem.NavigableDocument Document => INavigableItem.NavigableDocument.FromDocument(_workspace.CurrentSolution.Projects.Single().Documents.Single()); public TextSpan SourceSpan => _sourceSpan; public string AdditionalInformation => throw new NotImplementedException(); diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/DefaultNavigateToPreviewService.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/DefaultNavigateToPreviewService.cs index dab607a0ff8c6..db514260ce543 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/DefaultNavigateToPreviewService.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/DefaultNavigateToPreviewService.cs @@ -4,14 +4,16 @@ #nullable disable +using Microsoft.CodeAnalysis.Navigation; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; +using Microsoft.VisualStudio.Shell.Interop; namespace Microsoft.CodeAnalysis.Editor.Implementation.NavigateTo { internal sealed class DefaultNavigateToPreviewService : INavigateToPreviewService { - public int GetProvisionalViewingStatus(Document document) - => 0; + public __VSPROVISIONALVIEWINGSTATUS GetProvisionalViewingStatus(INavigableItem.NavigableDocument document) + => __VSPROVISIONALVIEWINGSTATUS.PVS_Disabled; public bool CanPreview(Document document) => true; diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/INavigateToPreviewService.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/INavigateToPreviewService.cs index 1c80806e78000..caa2ea2b02d8a 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/INavigateToPreviewService.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/INavigateToPreviewService.cs @@ -5,13 +5,15 @@ #nullable disable using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Navigation; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; +using Microsoft.VisualStudio.Shell.Interop; namespace Microsoft.CodeAnalysis.Editor.Implementation.NavigateTo { internal interface INavigateToPreviewService : IWorkspaceService { - int GetProvisionalViewingStatus(Document document); + __VSPROVISIONALVIEWINGSTATUS GetProvisionalViewingStatus(INavigableItem.NavigableDocument document); bool CanPreview(Document document); void PreviewItem(INavigateToItemDisplay itemDisplay); } diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemDisplay.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemDisplay.cs index af4844355fc48..2cf7dc85588cd 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemDisplay.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemDisplay.cs @@ -16,6 +16,7 @@ using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Imaging.Interop; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; +using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Utilities; using Roslyn.Utilities; @@ -63,9 +64,6 @@ private ReadOnlyCollection CreateDescriptionItems() return new List().AsReadOnly(); } - var sourceText = document.GetTextSynchronously(CancellationToken.None); - var span = NavigateToUtilities.GetBoundedSpan(_searchResult.NavigableItem, sourceText); - var items = new List { new DescriptionItem( @@ -78,13 +76,19 @@ private ReadOnlyCollection CreateDescriptionItems() new[] { new DescriptionRun("File:", bold: true) }), new ReadOnlyCollection( new[] { new DescriptionRun(document.FilePath ?? document.Name) })), - new DescriptionItem( - new ReadOnlyCollection( - new[] { new DescriptionRun("Line:", bold: true) }), - new ReadOnlyCollection( - new[] { new DescriptionRun((sourceText.Lines.IndexOf(span.Start) + 1).ToString()) })) }; + if (document.TryGetTextSynchronously(document.Workspace.CurrentSolution, CancellationToken.None) is { } sourceText) + { + var span = NavigateToUtilities.GetBoundedSpan(_searchResult.NavigableItem, sourceText); + items.Add( + new DescriptionItem( + new ReadOnlyCollection( + new[] { new DescriptionRun("Line:", bold: true) }), + new ReadOnlyCollection( + new[] { new DescriptionRun((sourceText.Lines.IndexOf(span.Start) + 1).ToString()) }))); + } + var summary = _searchResult.Summary; if (!string.IsNullOrWhiteSpace(summary)) { @@ -111,13 +115,13 @@ public int GetProvisionalViewingStatus() var document = _searchResult.NavigableItem.Document; if (document == null) { - return 0; + return (int)__VSPROVISIONALVIEWINGSTATUS.PVS_Disabled; } - var workspace = document.Project.Solution.Workspace; + var workspace = document.Workspace; var previewService = workspace.Services.GetService(); - return previewService.GetProvisionalViewingStatus(document); + return (int)previewService.GetProvisionalViewingStatus(document); } public void PreviewItem() @@ -128,7 +132,7 @@ public void PreviewItem() return; } - var workspace = document.Project.Solution.Workspace; + var workspace = document.Workspace; var previewService = workspace.Services.GetService(); previewService.PreviewItem(this); diff --git a/src/EditorFeatures/Core.Wpf/Peek/PeekableItemSource.cs b/src/EditorFeatures/Core.Wpf/Peek/PeekableItemSource.cs index 933d0bb334382..51480e02a54fb 100644 --- a/src/EditorFeatures/Core.Wpf/Peek/PeekableItemSource.cs +++ b/src/EditorFeatures/Core.Wpf/Peek/PeekableItemSource.cs @@ -136,7 +136,7 @@ public void AugmentPeekSession(IPeekSession session, IList peekab if (await navigationService.CanNavigateToPositionAsync( workspace, document.Id, item.SourceSpan.Start, cancellationToken).ConfigureAwait(false)) { - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var text = await document.GetTextAsync(project.Solution, cancellationToken).ConfigureAwait(false); var linePositionSpan = text.Lines.GetLinePositionSpan(item.SourceSpan); if (document.FilePath != null) { diff --git a/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs b/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs index e70161c966b3b..abe65bdde88ef 100644 --- a/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs +++ b/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs @@ -171,7 +171,7 @@ private async Task UpdateForCaretPositionAsync(SnapshotPoint pointInRoslynSnapsh { if (await navigationService.CanNavigateToSpanAsync(workspace, item.Document.Id, item.SourceSpan, cancellationToken).ConfigureAwait(false)) { - var text = await item.Document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var text = await item.Document.GetTextAsync(document.Project.Solution, cancellationToken).ConfigureAwait(false); var linePositionSpan = text.Lines.GetLinePositionSpan(item.SourceSpan); if (item.Document.FilePath != null) diff --git a/src/EditorFeatures/Core/NavigateTo/NavigateToHelpers.cs b/src/EditorFeatures/Core/NavigateTo/NavigateToHelpers.cs index 905e681c594a6..8147413c8415d 100644 --- a/src/EditorFeatures/Core/NavigateTo/NavigateToHelpers.cs +++ b/src/EditorFeatures/Core/NavigateTo/NavigateToHelpers.cs @@ -35,7 +35,7 @@ internal static class NavigateToHelpers if (document == null) return; - var workspace = document.Project.Solution.Workspace; + var workspace = document.Workspace; var navigationService = workspace.Services.GetRequiredService(); // Document tabs opened by NavigateTo are carefully created as preview or regular tabs diff --git a/src/EditorFeatures/Test2/CodeDefinitionWindow/CrossLanguageCodeDefinitionWindowTests.vb b/src/EditorFeatures/Test2/CodeDefinitionWindow/CrossLanguageCodeDefinitionWindowTests.vb index 7ff69e2a3dffb..cb77153a73490 100644 --- a/src/EditorFeatures/Test2/CodeDefinitionWindow/CrossLanguageCodeDefinitionWindowTests.vb +++ b/src/EditorFeatures/Test2/CodeDefinitionWindow/CrossLanguageCodeDefinitionWindowTests.vb @@ -22,10 +22,10 @@ Namespace Microsoft.CodeAnalysis.Editor.CodeDefinitionWindow.UnitTests Private Class FakeNavigableItem Implements INavigableItem - Private ReadOnly _document As Document + Private ReadOnly _document As INavigableItem.NavigableDocument Public Sub New(document As Document) - _document = document + _document = INavigableItem.NavigableDocument.FromDocument(document) End Sub Public ReadOnly Property ChildItems As ImmutableArray(Of INavigableItem) Implements INavigableItem.ChildItems @@ -46,7 +46,7 @@ Namespace Microsoft.CodeAnalysis.Editor.CodeDefinitionWindow.UnitTests End Get End Property - Public ReadOnly Property Document As Document Implements INavigableItem.Document + Public ReadOnly Property Document As INavigableItem.NavigableDocument Implements INavigableItem.Document Get Return _document End Get diff --git a/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxComparerTests.vb b/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxComparerTests.vb index bc9157327a0f2..07ecb356a0d46 100644 --- a/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxComparerTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EditAndContinue/SyntaxComparerTests.vb @@ -75,7 +75,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests End Sub - Public Sub ComputeDistance1() + Public Sub ComputeDistance_Nodes() Dim distance = SyntaxComparer.ComputeDistance( {MakeLiteral(0), MakeLiteral(1), MakeLiteral(2)}, {MakeLiteral(1), MakeLiteral(3)}) @@ -84,16 +84,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests End Sub - Public Sub ComputeDistance2() - Dim distance = SyntaxComparer.ComputeDistance( - ImmutableArray.Create(MakeLiteral(0), MakeLiteral(1), MakeLiteral(2)), - ImmutableArray.Create(MakeLiteral(1), MakeLiteral(3))) - - Assert.Equal(0.67, Math.Round(distance, 2)) - End Sub - - - Public Sub ComputeDistance3() + Public Sub ComputeDistance_Tokens() Dim distance = SyntaxComparer.ComputeDistance( {SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)}, {SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)}) @@ -160,5 +151,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Assert.Equal(0.0, Math.Round(distance, 2)) End Sub + + + Public Sub ComputeDistance_LongSequences() + Dim t1 = SyntaxFactory.Token(SyntaxKind.PublicKeyword) + Dim t2 = SyntaxFactory.Token(SyntaxKind.PrivateKeyword) + Dim t3 = SyntaxFactory.Token(SyntaxKind.ProtectedKeyword) + + Dim distance = SyntaxComparer.ComputeDistance( + Enumerable.Range(0, 10000).Select(Function(i) If(i < 2000, t1, t2)), + Enumerable.Range(0, 10000).Select(Function(i) If(i < 2000, t1, t3))) + + ' long sequences are indistinguishable if they have common prefix shorter then threshold + Assert.Equal(0.0, distance) + End Sub End Class End Namespace diff --git a/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs b/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs index 5bac6a333b59f..3691538e5f7f5 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/SyntaxComparer.cs @@ -7,6 +7,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Linq; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Differencing; @@ -1593,16 +1594,12 @@ public static double ComputeDistance(SyntaxNode? oldNode, SyntaxNode? newNode) /// Distance is a number within [0, 1], the smaller the more similar the tokens are. /// public static double ComputeDistance(SyntaxToken oldToken, SyntaxToken newToken) - => LongestCommonSubstring.ComputeDistance(oldToken.Text, newToken.Text); + => LongestCommonSubstring.ComputePrefixDistance( + oldToken.Text, Math.Min(oldToken.Text.Length, LongestCommonSubsequence.MaxSequenceLengthForDistanceCalculation), + newToken.Text, Math.Min(newToken.Text.Length, LongestCommonSubsequence.MaxSequenceLengthForDistanceCalculation)); - /// - /// Calculates the distance between two sequences of syntax tokens, disregarding trivia. - /// - /// - /// Distance is a number within [0, 1], the smaller the more similar the sequences are. - /// - public static double ComputeDistance(IEnumerable? oldTokens, IEnumerable? newTokens) - => LcsTokens.Instance.ComputeDistance(oldTokens.AsImmutableOrEmpty(), newTokens.AsImmutableOrEmpty()); + private static ImmutableArray CreateArrayForDistanceCalculation(IEnumerable? enumerable) + => enumerable is null ? ImmutableArray.Empty : enumerable.Take(LongestCommonSubsequence.MaxSequenceLengthForDistanceCalculation).ToImmutableArray(); /// /// Calculates the distance between two sequences of syntax tokens, disregarding trivia. @@ -1610,8 +1607,8 @@ public static double ComputeDistance(IEnumerable? oldTokens, IEnume /// /// Distance is a number within [0, 1], the smaller the more similar the sequences are. /// - public static double ComputeDistance(ImmutableArray oldTokens, ImmutableArray newTokens) - => LcsTokens.Instance.ComputeDistance(oldTokens.NullToEmpty(), newTokens.NullToEmpty()); + public static double ComputeDistance(IEnumerable? oldTokens, IEnumerable? newTokens) + => LcsTokens.Instance.ComputeDistance(CreateArrayForDistanceCalculation(oldTokens), CreateArrayForDistanceCalculation(newTokens)); /// /// Calculates the distance between two sequences of syntax nodes, disregarding trivia. @@ -1620,16 +1617,7 @@ public static double ComputeDistance(ImmutableArray oldTokens, Immu /// Distance is a number within [0, 1], the smaller the more similar the sequences are. /// public static double ComputeDistance(IEnumerable? oldNodes, IEnumerable? newNodes) - => LcsNodes.Instance.ComputeDistance(oldNodes.AsImmutableOrEmpty(), newNodes.AsImmutableOrEmpty()); - - /// - /// Calculates the distance between two sequences of syntax tokens, disregarding trivia. - /// - /// - /// Distance is a number within [0, 1], the smaller the more similar the sequences are. - /// - public static double ComputeDistance(ImmutableArray oldNodes, ImmutableArray newNodes) - => LcsNodes.Instance.ComputeDistance(oldNodes.NullToEmpty(), newNodes.NullToEmpty()); + => LcsNodes.Instance.ComputeDistance(CreateArrayForDistanceCalculation(oldNodes), CreateArrayForDistanceCalculation(newNodes)); /// /// Calculates the edits that transform one sequence of syntax nodes to another, disregarding trivia. diff --git a/src/Features/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs b/src/Features/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs index 6e2168987e923..c2bce6842af06 100644 --- a/src/Features/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs +++ b/src/Features/CSharpTest/GenerateFromMembers/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersTests.cs @@ -89,7 +89,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -131,7 +131,7 @@ class Program } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -180,7 +180,7 @@ class Program } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int, string)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i, string s)"), codeAction.Title) }.RunAsync(); } @@ -227,7 +227,7 @@ class Program } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int, string)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i, string s)"), codeAction.Title) }.RunAsync(); } @@ -274,7 +274,7 @@ class Program } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int, string)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i, string s)"), codeAction.Title) }.RunAsync(); } @@ -316,7 +316,7 @@ public Program(int i, string s = null) } """, CodeActionIndex = 1, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_optional_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_optional_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -371,7 +371,7 @@ public Program(int i, string s, bool b) : this(i) } """, CodeActionIndex = 1, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "Program(int, string)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "Program(int i, string s)"), codeAction.Title) }.RunAsync(); } @@ -426,7 +426,7 @@ public Program(int i, string s, bool b = false) : this(i) } """, CodeActionIndex = 3, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "Program(int, string)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "Program(int i, string s)"), codeAction.Title) }.RunAsync(); } @@ -466,7 +466,7 @@ public Program(bool b, HashSet s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(bool)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(bool b)"), codeAction.Title) }.RunAsync(); } @@ -507,7 +507,7 @@ public Program(bool b, HashSet s = null) } """, CodeActionIndex = 1, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_optional_parameters_to_0, "Program(bool)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_optional_parameters_to_0, "Program(bool b)"), codeAction.Title) }.RunAsync(); } @@ -1195,7 +1195,7 @@ public C(int i, int j, int k) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i)"), codeAction.Title) }.RunAsync(); } @@ -1240,7 +1240,7 @@ public C(int i, int j, int l) TestCode = source, FixedCode = expected, CodeActionIndex = 1, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i, int j)"), codeAction.Title) }.RunAsync(); } @@ -1286,7 +1286,7 @@ public C(int i, int j, int k, int l) TestCode = source, FixedCode = expected, CodeActionIndex = 2, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, int, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i, int j, int k)"), codeAction.Title) }.RunAsync(); } @@ -1331,7 +1331,7 @@ public C(int i, int j, int k) TestCode = source, FixedCode = expected, CodeActionIndex = 3, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i)"), codeAction.Title) }.RunAsync(); } @@ -1377,7 +1377,7 @@ public C(int i, int j, int l = 0) TestCode = source, FixedCode = expected, CodeActionIndex = 4, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i, int j)"), codeAction.Title) }.RunAsync(); } @@ -1422,7 +1422,7 @@ public C(int i, int j, int k, int l = 0) TestCode = source, FixedCode = expected, CodeActionIndex = 5, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, int, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i, int j, int k)"), codeAction.Title) }.RunAsync(); } @@ -1483,7 +1483,7 @@ public C(int i, double j, int k, int l) TestCode = source, FixedCode = expected, CodeActionIndex = 1, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, double, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i, double j, int k)"), codeAction.Title) }.RunAsync(); } @@ -1540,7 +1540,7 @@ public C(int i, double j = 0, int l = 0) TestCode = source, FixedCode = expected, CodeActionIndex = 3, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, double)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i, double j)"), codeAction.Title) }.RunAsync(); } @@ -1582,7 +1582,7 @@ public C(int l, double m, int n = 0) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int i)"), codeAction.Title) }.RunAsync(); } @@ -1627,7 +1627,7 @@ public C(int l, double m, int n = 0, int p = 0) TestCode = source, FixedCode = expected, CodeActionIndex = 2, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int, double, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(CodeFixesResources.Add_to_0, "C(int l, double m, int n)"), codeAction.Title) }.RunAsync(); } @@ -1945,7 +1945,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -1985,7 +1985,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2025,7 +2025,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2065,7 +2065,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2105,7 +2105,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2145,7 +2145,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2186,7 +2186,7 @@ public Program(int i, string s, string t) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2227,7 +2227,7 @@ public Program(int i, string s, string t) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2267,7 +2267,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2307,7 +2307,7 @@ public Program(int i, string s) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2347,7 +2347,7 @@ public Program(int i, string t) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2387,7 +2387,7 @@ public Program(int i, string t) } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "Program(int i)"), codeAction.Title) }.RunAsync(); } @@ -2690,7 +2690,7 @@ public class C } } """, - CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "C(int, int)"), codeAction.Title) + CodeActionVerifier = (codeAction, verifier) => verifier.Equal(string.Format(FeaturesResources.Add_parameters_to_0, "C(int original, int original2)"), codeAction.Title) }.RunAsync(); } diff --git a/src/Features/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs b/src/Features/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs index 4a6b497bfabfd..ced525a38e768 100644 --- a/src/Features/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs +++ b/src/Features/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs @@ -741,7 +741,7 @@ class Program HashSet s;|] } """, -string.Format(FeaturesResources.Generate_constructor_0_1, "Program", "bool, HashSet")); +string.Format(FeaturesResources.Generate_constructor_0_1, "Program", "bool b, HashSet s")); } [Fact] @@ -762,7 +762,7 @@ public Program(bool b) } } """, -string.Format(FeaturesResources.Generate_field_assigning_constructor_0_1, "Program", "bool, HashSet")); +string.Format(FeaturesResources.Generate_field_assigning_constructor_0_1, "Program", "bool b, HashSet s")); } [Fact] @@ -783,7 +783,7 @@ public Program(bool b) } } """, -string.Format(FeaturesResources.Generate_delegating_constructor_0_1, "Program", "bool, HashSet"), +string.Format(FeaturesResources.Generate_delegating_constructor_0_1, "Program", "bool b, HashSet s"), index: 1); } diff --git a/src/Features/Core/Portable/ExternalAccess/VSTypeScript/VSTypeScriptNavigableItemWrapper.cs b/src/Features/Core/Portable/ExternalAccess/VSTypeScript/VSTypeScriptNavigableItemWrapper.cs index 17b596a41950b..779960a026bfa 100644 --- a/src/Features/Core/Portable/ExternalAccess/VSTypeScript/VSTypeScriptNavigableItemWrapper.cs +++ b/src/Features/Core/Portable/ExternalAccess/VSTypeScript/VSTypeScriptNavigableItemWrapper.cs @@ -12,10 +12,12 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript internal sealed class VSTypeScriptNavigableItemWrapper : INavigableItem { private readonly IVSTypeScriptNavigableItem _navigableItem; + private readonly INavigableItem.NavigableDocument _navigableDocument; public VSTypeScriptNavigableItemWrapper(IVSTypeScriptNavigableItem navigableItem) { _navigableItem = navigableItem; + _navigableDocument = INavigableItem.NavigableDocument.FromDocument(navigableItem.Document); } public Glyph Glyph => _navigableItem.Glyph; @@ -26,7 +28,7 @@ public VSTypeScriptNavigableItemWrapper(IVSTypeScriptNavigableItem navigableItem public bool IsImplicitlyDeclared => _navigableItem.IsImplicitlyDeclared; - public Document Document => _navigableItem.Document; + public INavigableItem.NavigableDocument Document => _navigableDocument; public TextSpan SourceSpan => _navigableItem.SourceSpan; diff --git a/src/Features/Core/Portable/NavigateTo/RoslynNavigateToItem.cs b/src/Features/Core/Portable/NavigateTo/RoslynNavigateToItem.cs index 8a7f21285b884..25215ea1b1093 100644 --- a/src/Features/Core/Portable/NavigateTo/RoslynNavigateToItem.cs +++ b/src/Features/Core/Portable/NavigateTo/RoslynNavigateToItem.cs @@ -3,8 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Serialization; using System.Threading; @@ -15,7 +15,6 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.NavigateTo { @@ -107,12 +106,12 @@ private class NavigateToSearchResult : INavigateToSearchResult, INavigableItem /// /// The that is contained within. /// - private readonly Document _itemDocument; + private readonly INavigableItem.NavigableDocument _itemDocument; /// /// The document the user was editing when they invoked the navigate-to operation. /// - private readonly Document? _activeDocument; + private readonly (DocumentId id, IReadOnlyList folders)? _activeDocument; private readonly string _additionalInformation; private readonly Lazy _secondarySort; @@ -123,33 +122,35 @@ private class NavigateToSearchResult : INavigateToSearchResult, INavigableItem Document? activeDocument) { _item = item; - _itemDocument = itemDocument; - _activeDocument = activeDocument; - _additionalInformation = ComputeAdditionalInformation(); + _itemDocument = INavigableItem.NavigableDocument.FromDocument(itemDocument); + if (activeDocument is not null) + _activeDocument = (activeDocument.Id, activeDocument.Folders); + + _additionalInformation = ComputeAdditionalInformation(in item, itemDocument); _secondarySort = new Lazy(ComputeSecondarySort); } - private string ComputeAdditionalInformation() + private static string ComputeAdditionalInformation(in RoslynNavigateToItem item, Document itemDocument) { // For partial types, state what file they're in so the user can disambiguate the results. - var combinedProjectName = ComputeCombinedProjectName(); - return (_item.DeclaredSymbolInfo.IsPartial, IsNonNestedNamedType()) switch + var combinedProjectName = ComputeCombinedProjectName(in item, itemDocument); + return (item.DeclaredSymbolInfo.IsPartial, IsNonNestedNamedType(in item)) switch { - (true, true) => string.Format(FeaturesResources._0_dash_1, _itemDocument.Name, combinedProjectName), - (true, false) => string.Format(FeaturesResources.in_0_1_2, _item.DeclaredSymbolInfo.ContainerDisplayName, _itemDocument.Name, combinedProjectName), + (true, true) => string.Format(FeaturesResources._0_dash_1, itemDocument.Name, combinedProjectName), + (true, false) => string.Format(FeaturesResources.in_0_1_2, item.DeclaredSymbolInfo.ContainerDisplayName, itemDocument.Name, combinedProjectName), (false, true) => string.Format(FeaturesResources.project_0, combinedProjectName), - (false, false) => string.Format(FeaturesResources.in_0_project_1, _item.DeclaredSymbolInfo.ContainerDisplayName, combinedProjectName), + (false, false) => string.Format(FeaturesResources.in_0_project_1, item.DeclaredSymbolInfo.ContainerDisplayName, combinedProjectName), }; } - private string ComputeCombinedProjectName() + private static string ComputeCombinedProjectName(in RoslynNavigateToItem item, Document itemDocument) { // If there aren't any additional matches in other projects, we don't need to merge anything. - if (_item.AdditionalMatchingProjects.Length > 0) + if (item.AdditionalMatchingProjects.Length > 0) { // First get the simple project name and flavor for the actual project we got a hit in. If we can't // figure this out, we can't create a merged name. - var firstProject = _itemDocument.Project; + var firstProject = itemDocument.Project; var (firstProjectName, firstProjectFlavor) = firstProject.State.NameAndFlavor; if (firstProjectName != null) @@ -162,7 +163,7 @@ private string ComputeCombinedProjectName() // Now, do the same for the other projects where we had a match. As above, if we can't figure out the // simple name/flavor, or if the simple project name doesn't match the simple project name we started // with then we can't merge these. - foreach (var additionalProjectId in _item.AdditionalMatchingProjects) + foreach (var additionalProjectId in item.AdditionalMatchingProjects) { var additionalProject = solution.GetRequiredProject(additionalProjectId); var (projectName, projectFlavor) = additionalProject.State.NameAndFlavor; @@ -178,17 +179,17 @@ private string ComputeCombinedProjectName() } // Couldn't compute a merged project name (or only had one project). Just return the name of hte project itself. - return _itemDocument.Project.Name; + return itemDocument.Project.Name; } string INavigateToSearchResult.AdditionalInformation => _additionalInformation; - private bool IsNonNestedNamedType() - => !_item.DeclaredSymbolInfo.IsNestedType && IsNamedType(); + private static bool IsNonNestedNamedType(in RoslynNavigateToItem item) + => !item.DeclaredSymbolInfo.IsNestedType && IsNamedType(in item); - private bool IsNamedType() + private static bool IsNamedType(in RoslynNavigateToItem item) { - switch (_item.DeclaredSymbolInfo.Kind) + switch (item.DeclaredSymbolInfo.Kind) { case DeclaredSymbolInfoKind.Class: case DeclaredSymbolInfoKind.Record: @@ -243,14 +244,14 @@ private string ComputeSecondarySort() int ComputeFolderDistance() { // No need to compute anything if there is no active document. Consider all documents equal. - if (_activeDocument == null) + if (_activeDocument is not { } activeDocument) return 0; // The result was in the active document, this get highest priority. - if (_activeDocument == _itemDocument) + if (activeDocument.id == _itemDocument.Id) return 0; - var activeFolders = _activeDocument.Folders; + var activeFolders = activeDocument.folders; var itemFolders = _itemDocument.Folders; // see how many folder they have in common. @@ -263,21 +264,21 @@ int ComputeFolderDistance() // Add one more to the result. This way if they share all the same folders that we still return // '1', indicating that this close to, but not as good a match as an exact file match. return activeDiff + itemDiff + 1; - } - - int GetCommonFolderCount() - { - var activeFolders = _activeDocument.Folders; - var itemFolders = _itemDocument.Folders; - var maxCommon = Math.Min(activeFolders.Count, itemFolders.Count); - for (var i = 0; i < maxCommon; i++) + int GetCommonFolderCount() { - if (activeFolders[i] != itemFolders[i]) - return i; - } + var activeFolders = activeDocument.folders; + var itemFolders = _itemDocument.Folders; - return maxCommon; + var maxCommon = Math.Min(activeFolders.Count, itemFolders.Count); + for (var i = 0; i < maxCommon; i++) + { + if (activeFolders[i] != itemFolders[i]) + return i; + } + + return maxCommon; + } } } @@ -353,7 +354,7 @@ ImmutableArray INavigableItem.DisplayTaggedParts /// bool INavigableItem.IsImplicitlyDeclared => false; - Document INavigableItem.Document => _itemDocument; + INavigableItem.NavigableDocument INavigableItem.Document => _itemDocument; TextSpan INavigableItem.SourceSpan => _item.DeclaredSymbolInfo.Span; diff --git a/src/Features/Core/Portable/Navigation/INavigableItem.cs b/src/Features/Core/Portable/Navigation/INavigableItem.cs index 14b31b6a0912b..cc4d24811b6de 100644 --- a/src/Features/Core/Portable/Navigation/INavigableItem.cs +++ b/src/Features/Core/Portable/Navigation/INavigableItem.cs @@ -2,9 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - +using System.Collections.Generic; using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Navigation @@ -33,7 +35,7 @@ internal interface INavigableItem /// bool IsImplicitlyDeclared { get; } - Document Document { get; } + NavigableDocument Document { get; } TextSpan SourceSpan { get; } /// @@ -45,5 +47,50 @@ internal interface INavigableItem bool IsStale { get; } ImmutableArray ChildItems { get; } + + public record NavigableDocument(NavigableProject Project, string Name, string? FilePath, IReadOnlyList Folders, DocumentId Id, bool IsSourceGeneratedDocument, Workspace Workspace) + { + public static NavigableDocument FromDocument(Document document) + => new( + NavigableProject.FromProject(document.Project), + document.Name, + document.FilePath, + document.Folders, + document.Id, + IsSourceGeneratedDocument: document is SourceGeneratedDocument, + document.Project.Solution.Workspace); + + /// + /// Get the within which is referenced by + /// this navigable item. The document is required to exist within the solution, e.g. a case where the + /// navigable item was constructed during a Find Symbols operation on the same solution instance. + /// + internal ValueTask GetRequiredDocumentAsync(Solution solution, CancellationToken cancellationToken) + => solution.GetRequiredDocumentAsync(Id, includeSourceGenerated: IsSourceGeneratedDocument, cancellationToken); + + /// + /// Get the of the within + /// which is referenced by this navigable item. The document is required to + /// exist within the solution, e.g. a case where the navigable item was constructed during a Find Symbols + /// operation on the same solution instance. + /// + internal async ValueTask GetTextAsync(Solution solution, CancellationToken cancellationToken) + { + var document = await GetRequiredDocumentAsync(solution, cancellationToken).ConfigureAwait(false); + return await document.GetValueTextAsync(cancellationToken).ConfigureAwait(false); + } + + internal SourceText? TryGetTextSynchronously(Solution solution, CancellationToken cancellationToken) + { + var document = solution.GetDocument(Id); + return document?.GetTextSynchronously(cancellationToken); + } + } + + public record struct NavigableProject(string Name, ProjectId Id) + { + public static NavigableProject FromProject(Project project) + => new(project.Name, project.Id); + } } } diff --git a/src/Features/Core/Portable/Navigation/NavigableItemFactory.SymbolLocationNavigableItem.cs b/src/Features/Core/Portable/Navigation/NavigableItemFactory.SymbolLocationNavigableItem.cs index afc361db4d749..e8c50745f0684 100644 --- a/src/Features/Core/Portable/Navigation/NavigableItemFactory.SymbolLocationNavigableItem.cs +++ b/src/Features/Core/Portable/Navigation/NavigableItemFactory.SymbolLocationNavigableItem.cs @@ -4,9 +4,12 @@ #nullable disable +using System; using System.Collections.Immutable; +using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Navigation { @@ -18,6 +21,12 @@ private class SymbolLocationNavigableItem : INavigableItem private readonly ISymbol _symbol; private readonly Location _location; + /// + /// Lazily-initialized backing field for . + /// + /// + private StrongBox _lazyDocument; + public SymbolLocationNavigableItem( Solution solution, ISymbol symbol, @@ -38,8 +47,21 @@ private class SymbolLocationNavigableItem : INavigableItem public bool IsImplicitlyDeclared => _symbol.IsImplicitlyDeclared; - public Document Document - => _location.IsInSource ? _solution.GetDocument(_location.SourceTree) : null; + public INavigableItem.NavigableDocument Document + { + get + { + return LazyInitialization.EnsureInitialized( + ref _lazyDocument, + static self => + { + return (self._location.IsInSource && self._solution.GetDocument(self._location.SourceTree) is { } document) + ? INavigableItem.NavigableDocument.FromDocument(document) + : null; + }, + this); + } + } public TextSpan SourceSpan => _location.SourceSpan; diff --git a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs index 7cdda74d38f61..937cfeda9a8a5 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs @@ -200,10 +200,12 @@ public static LSP.VersionedTextDocumentIdentifier DocumentToVersionedTextDocumen public static LinePosition PositionToLinePosition(LSP.Position position) => new LinePosition(position.Line, position.Character); + public static LinePositionSpan RangeToLinePositionSpan(LSP.Range range) + => new(PositionToLinePosition(range.Start), PositionToLinePosition(range.End)); public static TextSpan RangeToTextSpan(LSP.Range range, SourceText text) { - var linePositionSpan = new LinePositionSpan(PositionToLinePosition(range.Start), PositionToLinePosition(range.End)); + var linePositionSpan = RangeToLinePositionSpan(range); try { diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs index 4c729a7fcc5dd..7e4c51e8713cb 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs @@ -59,7 +59,10 @@ public AbstractGoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSour } var location = await ProtocolConversions.TextSpanToLocationAsync( - definition.Document, definition.SourceSpan, definition.IsStale, cancellationToken).ConfigureAwait(false); + await definition.Document.GetRequiredDocumentAsync(document.Project.Solution, cancellationToken).ConfigureAwait(false), + definition.SourceSpan, + definition.IsStale, + cancellationToken).ConfigureAwait(false); locations.AddIfNotNull(location); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Symbols/WorkspaceSymbolsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Symbols/WorkspaceSymbolsHandler.cs index 8d742c720c224..108cb201a8283 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Symbols/WorkspaceSymbolsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Symbols/WorkspaceSymbolsHandler.cs @@ -85,8 +85,10 @@ private class LSPNavigateToCallback : INavigateToSearchCallback public async Task AddItemAsync(Project project, INavigateToSearchResult result, CancellationToken cancellationToken) { + var document = await result.NavigableItem.Document.GetRequiredDocumentAsync(project.Solution, cancellationToken).ConfigureAwait(false); + var location = await ProtocolConversions.TextSpanToLocationAsync( - result.NavigableItem.Document, result.NavigableItem.SourceSpan, result.NavigableItem.IsStale, _context, cancellationToken).ConfigureAwait(false); + document, result.NavigableItem.SourceSpan, result.NavigableItem.IsStale, _context, cancellationToken).ConfigureAwait(false); if (location == null) return; diff --git a/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxComparer.vb b/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxComparer.vb index 93779fa9af5d5..dec16319bd967 100644 --- a/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxComparer.vb +++ b/src/Features/VisualBasic/Portable/EditAndContinue/SyntaxComparer.vb @@ -9,7 +9,6 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue Friend NotInheritable Class SyntaxComparer - Inherits AbstractSyntaxComparer Friend Shared ReadOnly TopLevel As SyntaxComparer = New SyntaxComparer(Nothing, Nothing, Nothing, Nothing, compareStatementSyntax:=False) @@ -1389,17 +1388,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue ''' Distance is a number within [0, 1], the smaller the more similar the tokens are. ''' Public Overloads Shared Function ComputeDistance(oldToken As SyntaxToken, newToken As SyntaxToken) As Double - Return LongestCommonSubstring.ComputeDistance(oldToken.ValueText, newToken.ValueText) + Return LongestCommonSubstring.ComputePrefixDistance( + oldToken.Text, Math.Min(oldToken.Text.Length, LongestCommonSubsequence.MaxSequenceLengthForDistanceCalculation), + newToken.Text, Math.Min(newToken.Text.Length, LongestCommonSubsequence.MaxSequenceLengthForDistanceCalculation)) End Function - ''' - ''' Calculates the distance between two sequences of syntax tokens, disregarding trivia. - ''' - ''' - ''' Distance is a number within [0, 1], the smaller the more similar the sequences are. - ''' - Public Overloads Shared Function ComputeDistance(oldTokens As IEnumerable(Of SyntaxToken), newTokens As IEnumerable(Of SyntaxToken)) As Double - Return ComputeDistance(oldTokens.AsImmutableOrNull(), newTokens.AsImmutableOrNull()) + Private Shared Function CreateArrayForDistanceCalculation(Of T)(enumerable As IEnumerable(Of T)) As ImmutableArray(Of T) + Return If(enumerable Is Nothing, ImmutableArray(Of T).Empty, enumerable.Take(LongestCommonSubsequence.MaxSequenceLengthForDistanceCalculation).ToImmutableArray()) End Function ''' @@ -1408,8 +1403,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue ''' ''' Distance is a number within [0, 1], the smaller the more similar the sequences are. ''' - Public Overloads Shared Function ComputeDistance(oldTokens As ImmutableArray(Of SyntaxToken), newTokens As ImmutableArray(Of SyntaxToken)) As Double - Return LcsTokens.Instance.ComputeDistance(oldTokens.NullToEmpty(), newTokens.NullToEmpty()) + Public Overloads Shared Function ComputeDistance(oldTokens As IEnumerable(Of SyntaxToken), newTokens As IEnumerable(Of SyntaxToken)) As Double + Return LcsTokens.Instance.ComputeDistance(CreateArrayForDistanceCalculation(oldTokens), CreateArrayForDistanceCalculation(newTokens)) End Function ''' @@ -1419,17 +1414,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue ''' Distance is a number within [0, 1], the smaller the more similar the sequences are. ''' Public Overloads Shared Function ComputeDistance(oldTokens As IEnumerable(Of SyntaxNode), newTokens As IEnumerable(Of SyntaxNode)) As Double - Return ComputeDistance(oldTokens.AsImmutableOrNull(), newTokens.AsImmutableOrNull()) - End Function - - ''' - ''' Calculates the distance between two sequences of syntax nodes, disregarding trivia. - ''' - ''' - ''' Distance is a number within [0, 1], the smaller the more similar the sequences are. - ''' - Public Overloads Shared Function ComputeDistance(oldTokens As ImmutableArray(Of SyntaxNode), newTokens As ImmutableArray(Of SyntaxNode)) As Double - Return LcsNodes.Instance.ComputeDistance(oldTokens.NullToEmpty(), newTokens.NullToEmpty()) + Return LcsNodes.Instance.ComputeDistance(CreateArrayForDistanceCalculation(oldTokens), CreateArrayForDistanceCalculation(newTokens)) End Function ''' diff --git a/src/Tools/ExternalAccess/FSharp/Internal/Navigation/InternalFSharpNavigableItem.cs b/src/Tools/ExternalAccess/FSharp/Internal/Navigation/InternalFSharpNavigableItem.cs index 158a8d99bb399..48cadf77ebc2e 100644 --- a/src/Tools/ExternalAccess/FSharp/Internal/Navigation/InternalFSharpNavigableItem.cs +++ b/src/Tools/ExternalAccess/FSharp/Internal/Navigation/InternalFSharpNavigableItem.cs @@ -4,6 +4,7 @@ #nullable disable +using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.ExternalAccess.FSharp.Navigation; using Microsoft.CodeAnalysis.Navigation; @@ -13,11 +14,14 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.FSharp.Internal.Navigation { internal class InternalFSharpNavigableItem : INavigableItem { + private readonly INavigableItem.NavigableDocument _navigableDocument; + public InternalFSharpNavigableItem(FSharpNavigableItem item) { Glyph = FSharpGlyphHelpers.ConvertTo(item.Glyph); DisplayTaggedParts = item.DisplayTaggedParts; Document = item.Document; + _navigableDocument = INavigableItem.NavigableDocument.FromDocument(item.Document); SourceSpan = item.SourceSpan; } @@ -31,6 +35,8 @@ public InternalFSharpNavigableItem(FSharpNavigableItem item) public Document Document { get; } + INavigableItem.NavigableDocument INavigableItem.Document => _navigableDocument; + public TextSpan SourceSpan { get; } public bool IsStale => false; diff --git a/src/Tools/ExternalAccess/OmniSharp/GoToDefinition/OmniSharpFindDefinitionService.cs b/src/Tools/ExternalAccess/OmniSharp/GoToDefinition/OmniSharpFindDefinitionService.cs index 156b9e3c75623..43e2d9cd7492a 100644 --- a/src/Tools/ExternalAccess/OmniSharp/GoToDefinition/OmniSharpFindDefinitionService.cs +++ b/src/Tools/ExternalAccess/OmniSharp/GoToDefinition/OmniSharpFindDefinitionService.cs @@ -17,7 +17,10 @@ internal static async Task> FindDefinitio { var service = document.GetRequiredLanguageService(); var result = await service.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false); - return result.NullToEmpty().SelectAsArray(original => new OmniSharpNavigableItem(original.DisplayTaggedParts, original.Document, original.SourceSpan)); + return await result.NullToEmpty().SelectAsArrayAsync( + async (original, solution, cancellationToken) => new OmniSharpNavigableItem(original.DisplayTaggedParts, await original.Document.GetRequiredDocumentAsync(solution, cancellationToken).ConfigureAwait(false), original.SourceSpan), + document.Project.Solution, + cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Tools/ExternalAccess/OmniSharp/NavigateTo/OmniSharpNavigateToSearchService.cs b/src/Tools/ExternalAccess/OmniSharp/NavigateTo/OmniSharpNavigateToSearchService.cs index fabbeedf56a67..bc68564d8777f 100644 --- a/src/Tools/ExternalAccess/OmniSharp/NavigateTo/OmniSharpNavigateToSearchService.cs +++ b/src/Tools/ExternalAccess/OmniSharp/NavigateTo/OmniSharpNavigateToSearchService.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Navigation; @@ -45,8 +42,9 @@ public OmniSharpNavigateToCallbackImpl(OmniSharpNavigateToCallback callback) _callback = callback; } - public Task AddItemAsync(Project project, INavigateToSearchResult result, CancellationToken cancellationToken) + public async Task AddItemAsync(Project project, INavigateToSearchResult result, CancellationToken cancellationToken) { + var document = await result.NavigableItem.Document.GetRequiredDocumentAsync(project.Solution, cancellationToken).ConfigureAwait(false); var omniSharpResult = new OmniSharpNavigateToSearchResult( result.AdditionalInformation, result.Kind, @@ -56,9 +54,9 @@ public Task AddItemAsync(Project project, INavigateToSearchResult result, Cancel result.NameMatchSpans, result.SecondarySort, result.Summary!, - new(result.NavigableItem.DisplayTaggedParts, result.NavigableItem.Document, result.NavigableItem.SourceSpan)); + new OmniSharpNavigableItem(result.NavigableItem.DisplayTaggedParts, document, result.NavigableItem.SourceSpan)); - return _callback(project, omniSharpResult, cancellationToken); + await _callback(project, omniSharpResult, cancellationToken).ConfigureAwait(false); } public void Done(bool isFullyLoaded) diff --git a/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs b/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs index cbe8e0c3f9a4e..7784886c8e9da 100644 --- a/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs +++ b/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs @@ -8,9 +8,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Test.Utilities; -using Microsoft.VisualStudio.LanguageServer.Protocol; using Microsoft.VisualStudio.LanguageServices.DocumentOutline; using Microsoft.VisualStudio.Text; using Roslyn.Test.Utilities; @@ -95,7 +95,7 @@ static ImmutableArray Sort(ImmutableArray newChildren) { var data = symbolToUpdate.Data; - var symbolData = new DocumentSymbolData(data.Name, data.SymbolKind, data.Glyph, data.RangeSpan, data.SelectionRangeSpan, ImmutableArray.Empty); + var symbolData = data with { Children = ImmutableArray.Empty }; return new DocumentSymbolDataViewModel(symbolData, newChildren); } @@ -147,5 +147,61 @@ public async Task TestSearchDocumentSymbolData() searchedSymbols = DocumentOutlineViewModel.SearchDocumentSymbolData(model.DocumentSymbolData, "xyz", CancellationToken.None); Assert.Equal(0, searchedSymbols.Length); } + + [WpfFact] + [WorkItem("https://github.com/dotnet/roslyn/issues/66012")] + public async Task TestEnumOnSingleLine() + { + var (_, _, items) = await InitializeMocksAndDataModelAndUIItems( + """ + enum Test + { a, b } + """); + + Assert.Collection( + items, + item => + { + Assert.Equal(Glyph.EnumInternal, item.Data.Glyph); + Assert.Equal("Test", item.Data.Name); + Assert.Collection( + item.Children, + item => + { + Assert.Equal(Glyph.EnumMemberPublic, item.Data.Glyph); + Assert.Equal("a", item.Data.Name); + }, + item => + { + Assert.Equal(Glyph.EnumMemberPublic, item.Data.Glyph); + Assert.Equal("b", item.Data.Name); + }); + }); + } + + [WpfFact] + [WorkItem("https://github.com/dotnet/roslyn/issues/66473")] + public async Task TestClassOnSingleLine() + { + var (_, _, items) = await InitializeMocksAndDataModelAndUIItems( + """ + abstract class TypeName { public string PropertyName { get; } = "Value"; } + """); + + Assert.Collection( + items, + item => + { + Assert.Equal(Glyph.ClassInternal, item.Data.Glyph); + Assert.Equal("TypeName", item.Data.Name); + Assert.Collection( + item.Children, + item => + { + Assert.Equal(Glyph.PropertyPublic, item.Data.Glyph); + Assert.Equal("PropertyName", item.Data.Name); + }); + }); + } } } diff --git a/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTestsBase.cs b/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTestsBase.cs index 496b0d372182d..d78efbc4985d4 100644 --- a/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTestsBase.cs +++ b/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTestsBase.cs @@ -107,7 +107,7 @@ protected async Task CreateMocksAsync(string code) async Task RequestAsync(ITextBuffer textBuffer, Func capabilitiesFilter, string languageServerName, string method, Func parameterFactory, CancellationToken cancellationToken) { var request = parameterFactory(textBuffer.CurrentSnapshot).ToObject(); - var response = await testLspServer.ExecuteRequestAsync(method, request!, cancellationToken); + var response = await testLspServer.ExecuteRequestAsync(method, request!, cancellationToken); return new ManualInvocationResponse(string.Empty, JToken.FromObject(response!)); } } diff --git a/src/VisualStudio/Core/Def/Commands.vsct b/src/VisualStudio/Core/Def/Commands.vsct index acae0dfe7107b..a6e3826dd285a 100644 --- a/src/VisualStudio/Core/Def/Commands.vsct +++ b/src/VisualStudio/Core/Def/Commands.vsct @@ -68,6 +68,10 @@ + + + + @@ -533,6 +537,71 @@ ClearStackTraceExplorer + + + + + + + + + + @@ -618,6 +687,15 @@ StackTrace Explorer + + + + NotInTBList + + RoslynDocumentOutlineToolbar + Document Outline + + @@ -780,6 +858,14 @@ + + + + + + + + diff --git a/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineOptionsStorage.cs b/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineOptionsStorage.cs index 4f20a737432db..7d41c9ec82b30 100644 --- a/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineOptionsStorage.cs +++ b/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineOptionsStorage.cs @@ -12,5 +12,7 @@ namespace Microsoft.VisualStudio.LanguageServices.DocumentOutline internal sealed class DocumentOutlineOptionsStorage { public static readonly Option2 EnableDocumentOutline = new("visual_studio_enable_document_outline", defaultValue: false); + + public static readonly Option2 DocumentOutlineSortOrder = new("visual_studio_document_outline_sort_order", defaultValue: SortOption.Location); } } diff --git a/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineStrings.cs b/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineStrings.cs index 1d063a14ab79a..b9402a4af0609 100644 --- a/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineStrings.cs +++ b/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineStrings.cs @@ -6,22 +6,7 @@ namespace Microsoft.VisualStudio.LanguageServices.DocumentOutline { internal static class DocumentOutlineStrings { - public static string Document_Outline_Search - => ServicesVSResources.Document_Outline_Search; - - public static string Document_Outline_Expand_All - => ServicesVSResources.Document_Outline_Expand_All; - - public static string Document_Outline_Collapse_All - => ServicesVSResources.Document_Outline_Collapse_All; - - public static string Document_Outline_Sort_Name - => ServicesVSResources.Document_Outline_Sort_Name; - - public static string Document_Outline_Sort_Order - => ServicesVSResources.Document_Outline_Sort_Order; - - public static string Document_Outline_Sort_Type - => ServicesVSResources.Document_Outline_Sort_Type; + public static string Document_Outline + => ServicesVSResources.Document_Outline; } } diff --git a/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineView.xaml b/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineView.xaml index b287ded7f6353..30c0e9a4a4b53 100644 --- a/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineView.xaml +++ b/src/VisualStudio/Core/Def/DocumentOutline/DocumentOutlineView.xaml @@ -72,61 +72,12 @@ - - + + - - - - - - - - - - - - - - - - - - - + + - +