diff --git a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs index 2118d42475bc7..cffa1ed465e82 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs @@ -3742,6 +3742,38 @@ void Goo() Regex.Comment("(?#comment)")); } + [Theory, WorkItem(64549, "https://github.com/dotnet/roslyn/issues/64549")] + [CombinatorialData] + public async Task TestRegexOnApiWithStringSyntaxAttribute_ParamsArgument2(TestHost testHost) + { + await TestAsync( +@" +using System.Diagnostics.CodeAnalysis; +using System.Text.RegularExpressions; + +class Program +{ + private void M([StringSyntax(StringSyntaxAttribute.Regex)] params string[] p) + { + } + + void Goo() + { + [|M(@""$\a(?#comment)"", @""$\a(?#comment)"");|] + } +}" + EmbeddedLanguagesTestConstants.StringSyntaxAttributeCodeCSharp, +testHost, +Method("M"), +Regex.Anchor("$"), +Regex.OtherEscape("\\"), +Regex.OtherEscape("a"), +Regex.Comment("(?#comment)"), +Regex.Anchor("$"), +Regex.OtherEscape("\\"), +Regex.OtherEscape("a"), +Regex.Comment("(?#comment)")); + } + [Theory] [CombinatorialData] public async Task TestRegexOnApiWithStringSyntaxAttribute_ArrayArgument(TestHost testHost) diff --git a/src/Features/Core/Portable/EmbeddedLanguages/EmbeddedLanguageDetector.cs b/src/Features/Core/Portable/EmbeddedLanguages/EmbeddedLanguageDetector.cs index a399709766c12..fffd749016755 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/EmbeddedLanguageDetector.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/EmbeddedLanguageDetector.cs @@ -276,7 +276,7 @@ private bool IsAttributeArgumentWithMatchingStringSyntaxAttribute( return HasMatchingStringSyntaxAttribute(fieldOrProperty, out identifier); // Otherwise, see if it's a normal named/position argument to the attribute. - var parameter = Info.SemanticFacts.FindParameterForAttributeArgument(semanticModel, argument, allowUncertainCandidates: true, cancellationToken); + var parameter = Info.SemanticFacts.FindParameterForAttributeArgument(semanticModel, argument, allowUncertainCandidates: true, allowParams: true, cancellationToken); return HasMatchingStringSyntaxAttribute(parameter, out identifier); } @@ -290,7 +290,7 @@ private bool IsArgumentWithMatchingStringSyntaxAttribute( if (fieldOrProperty != null) return HasMatchingStringSyntaxAttribute(fieldOrProperty, out identifier); - var parameter = Info.SemanticFacts.FindParameterForArgument(semanticModel, argument, allowUncertainCandidates: true, cancellationToken); + var parameter = Info.SemanticFacts.FindParameterForArgument(semanticModel, argument, allowUncertainCandidates: true, allowParams: true, cancellationToken); return HasMatchingStringSyntaxAttribute(parameter, out identifier); } diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonLanguageDetector.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonLanguageDetector.cs index dd60351bf5a0c..fddc8de441756 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonLanguageDetector.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonLanguageDetector.cs @@ -212,7 +212,7 @@ protected override bool TryGetOptions( private bool IsArgumentToSuitableParameter( SemanticModel semanticModel, SyntaxNode argumentNode, CancellationToken cancellationToken) { - var parameter = Info.SemanticFacts.FindParameterForArgument(semanticModel, argumentNode, allowUncertainCandidates: true, cancellationToken); + var parameter = Info.SemanticFacts.FindParameterForArgument(semanticModel, argumentNode, allowUncertainCandidates: true, allowParams: true, cancellationToken); return parameter?.Name == JsonParameterName; } } diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexLanguageDetector.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexLanguageDetector.cs index 900a6b5d829e0..cf6a94487753b 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexLanguageDetector.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexLanguageDetector.cs @@ -192,7 +192,7 @@ private bool AnalyzeStringLiteral( { options = default; - var parameter = Info.SemanticFacts.FindParameterForArgument(semanticModel, argumentNode, allowUncertainCandidates: true, cancellationToken); + var parameter = Info.SemanticFacts.FindParameterForArgument(semanticModel, argumentNode, allowUncertainCandidates: true, allowParams: true, cancellationToken); if (parameter?.Name != _patternName) { return false; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SemanticFacts/CSharpSemanticFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SemanticFacts/CSharpSemanticFacts.cs index 8e895bd07ad85..66460b40e6566 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SemanticFacts/CSharpSemanticFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SemanticFacts/CSharpSemanticFacts.cs @@ -257,11 +257,11 @@ public IEnumerable GetDeclaredSymbols( } } - public IParameterSymbol FindParameterForArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, CancellationToken cancellationToken) - => ((ArgumentSyntax)argument).DetermineParameter(semanticModel, allowUncertainCandidates, allowParams: false, cancellationToken); + public IParameterSymbol FindParameterForArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, bool allowParams, CancellationToken cancellationToken) + => ((ArgumentSyntax)argument).DetermineParameter(semanticModel, allowUncertainCandidates, allowParams, cancellationToken); - public IParameterSymbol FindParameterForAttributeArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, CancellationToken cancellationToken) - => ((AttributeArgumentSyntax)argument).DetermineParameter(semanticModel, allowUncertainCandidates, allowParams: false, cancellationToken); + public IParameterSymbol FindParameterForAttributeArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, bool allowParams, CancellationToken cancellationToken) + => ((AttributeArgumentSyntax)argument).DetermineParameter(semanticModel, allowUncertainCandidates, allowParams, cancellationToken); // Normal arguments can't reference fields/properties in c# public ISymbol FindFieldOrPropertyForArgument(SemanticModel semanticModel, SyntaxNode argument, CancellationToken cancellationToken) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFacts.cs index acf4349d05186..496fa7a9634bd 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFacts.cs @@ -89,8 +89,8 @@ internal partial interface ISemanticFacts IEnumerable GetDeclaredSymbols(SemanticModel semanticModel, SyntaxNode memberDeclaration, CancellationToken cancellationToken); - IParameterSymbol FindParameterForArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, CancellationToken cancellationToken); - IParameterSymbol FindParameterForAttributeArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, CancellationToken cancellationToken); + IParameterSymbol FindParameterForArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, bool allowParams, CancellationToken cancellationToken); + IParameterSymbol FindParameterForAttributeArgument(SemanticModel semanticModel, SyntaxNode argument, bool allowUncertainCandidates, bool allowParams, CancellationToken cancellationToken); ISymbol FindFieldOrPropertyForArgument(SemanticModel semanticModel, SyntaxNode argument, CancellationToken cancellationToken); ISymbol FindFieldOrPropertyForAttributeArgument(SemanticModel semanticModel, SyntaxNode argument, CancellationToken cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFactsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFactsExtensions.cs index 2580904f6ddd7..b336b5720d672 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFactsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SemanticFacts/ISemanticFactsExtensions.cs @@ -119,9 +119,9 @@ private static bool IsFloatingPoint([NotNullWhen(returnValue: true)] ITypeSymbol => type?.SpecialType is SpecialType.System_Single or SpecialType.System_Double; public static IParameterSymbol FindParameterForArgument(this ISemanticFacts semanticFacts, SemanticModel semanticModel, SyntaxNode argument, CancellationToken cancellationToken) - => semanticFacts.FindParameterForArgument(semanticModel, argument, allowUncertainCandidates: false, cancellationToken); + => semanticFacts.FindParameterForArgument(semanticModel, argument, allowUncertainCandidates: false, allowParams: false, cancellationToken); public static IParameterSymbol FindParameterForAttributeArgument(this ISemanticFacts semanticFacts, SemanticModel semanticModel, SyntaxNode argument, CancellationToken cancellationToken) - => semanticFacts.FindParameterForAttributeArgument(semanticModel, argument, allowUncertainCandidates: false, cancellationToken); + => semanticFacts.FindParameterForAttributeArgument(semanticModel, argument, allowUncertainCandidates: false, allowParams: false, cancellationToken); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SemanticFacts/VisualBasicSemanticFacts.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SemanticFacts/VisualBasicSemanticFacts.vb index bd0fe30f25af0..881527bfd575a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SemanticFacts/VisualBasicSemanticFacts.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SemanticFacts/VisualBasicSemanticFacts.vb @@ -227,11 +227,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return SpecializedCollections.SingletonEnumerable(semanticModel.GetDeclaredSymbol(memberDeclaration, cancellationToken)) End Function - Public Function FindParameterForArgument(semanticModel As SemanticModel, argument As SyntaxNode, allowUncertainCandidates As Boolean, cancellationToken As CancellationToken) As IParameterSymbol Implements ISemanticFacts.FindParameterForArgument - Return DirectCast(argument, ArgumentSyntax).DetermineParameter(semanticModel, allowUncertainCandidates, allowParamArray:=False, cancellationToken) + Public Function FindParameterForArgument(semanticModel As SemanticModel, argument As SyntaxNode, allowUncertainCandidates As Boolean, allowParams As Boolean, cancellationToken As CancellationToken) As IParameterSymbol Implements ISemanticFacts.FindParameterForArgument + Return DirectCast(argument, ArgumentSyntax).DetermineParameter(semanticModel, allowUncertainCandidates, allowParams, cancellationToken) End Function - Public Function FindParameterForAttributeArgument(semanticModel As SemanticModel, argument As SyntaxNode, allowUncertainCandidates As Boolean, cancellationToken As CancellationToken) As IParameterSymbol Implements ISemanticFacts.FindParameterForAttributeArgument + Public Function FindParameterForAttributeArgument(semanticModel As SemanticModel, argument As SyntaxNode, allowUncertainCandidates As Boolean, allowParams As Boolean, cancellationToken As CancellationToken) As IParameterSymbol Implements ISemanticFacts.FindParameterForAttributeArgument Return Nothing End Function diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs index 48cd2011275b8..74fe45e631c31 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SemanticsFactsService/AbstractSemanticFactsService.cs @@ -153,11 +153,11 @@ public bool IsPartial(ITypeSymbol typeSymbol, CancellationToken cancellationToke public IEnumerable GetDeclaredSymbols(SemanticModel semanticModel, SyntaxNode memberDeclaration, CancellationToken cancellationToken) => SemanticFacts.GetDeclaredSymbols(semanticModel, memberDeclaration, cancellationToken); - public IParameterSymbol FindParameterForArgument(SemanticModel semanticModel, SyntaxNode argumentNode, bool allowUncertainCandidates, CancellationToken cancellationToken) - => SemanticFacts.FindParameterForArgument(semanticModel, argumentNode, allowUncertainCandidates, cancellationToken); + public IParameterSymbol FindParameterForArgument(SemanticModel semanticModel, SyntaxNode argumentNode, bool allowUncertainCandidates, bool allowParams, CancellationToken cancellationToken) + => SemanticFacts.FindParameterForArgument(semanticModel, argumentNode, allowUncertainCandidates, allowParams, cancellationToken); - public IParameterSymbol FindParameterForAttributeArgument(SemanticModel semanticModel, SyntaxNode argumentNode, bool allowUncertainCandidates, CancellationToken cancellationToken) - => SemanticFacts.FindParameterForAttributeArgument(semanticModel, argumentNode, allowUncertainCandidates, cancellationToken); + public IParameterSymbol FindParameterForAttributeArgument(SemanticModel semanticModel, SyntaxNode argumentNode, bool allowUncertainCandidates, bool allowParams, CancellationToken cancellationToken) + => SemanticFacts.FindParameterForAttributeArgument(semanticModel, argumentNode, allowUncertainCandidates, allowParams, cancellationToken); public ISymbol FindFieldOrPropertyForArgument(SemanticModel semanticModel, SyntaxNode argumentNode, CancellationToken cancellationToken) => SemanticFacts.FindFieldOrPropertyForArgument(semanticModel, argumentNode, cancellationToken);