Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix completion lists in primary constructor parameter lists #75266

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12622,6 +12622,23 @@ $$
End Function

<WpfTheory, CombinatorialData>
<WorkItem("https://github.com/dotnet/roslyn/issues/73120")>
Public Async Function TestAfterPrimaryConstructorAttribute(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
<Document>
class C([X] $$ client)
{
}
</Document>,
showCompletionInArgumentLists:=showCompletionInArgumentLists, languageVersion:=LanguageVersion.CSharp12)

state.SendInvokeCompletionList()
Await state.AssertCompletionSession()
Await state.AssertCompletionItemsContain("int", displayTextSuffix:="")
Await state.AssertCompletionItemsContain("System", displayTextSuffix:="")
End Using
End Function

<WorkItem("https://github.com/dotnet/roslyn/issues/72872")>
Public Async Function CompletionInsideImplicitObjectCreationInsideCollectionExpression(showCompletionInArgumentLists As Boolean) As Task
Using state = TestStateFactory.CreateCSharpTestState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,8 @@

namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders;

internal class IntKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender
internal sealed class IntKeywordRecommender() : AbstractSpecialTypePreselectingKeywordRecommender(SyntaxKind.IntKeyword)
{
public IntKeywordRecommender()
: base(SyntaxKind.IntKeyword)
{
}

protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken)
{
var syntaxTree = context.SyntaxTree;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CompilationUnitSyntaxExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ContextQuery\CSharpSyntaxContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ContextQuery\CSharpSyntaxContextService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ContextQuery\SyntaxNodeExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ContextQuery\SyntaxTokenExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ContextQuery\SyntaxTreeExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\DocumentationCommentExtensions.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
namespace Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;

[ExportLanguageService(typeof(ISyntaxContextService), LanguageNames.CSharp), Shared]
internal class CSharpSyntaxContextService : ISyntaxContextService
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class CSharpSyntaxContextService() : ISyntaxContextService
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpSyntaxContextService()
{
}

public SyntaxContext CreateContext(Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken)
=> CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,8 @@ public static bool IsParameterModifierContext(
previousModifier = SyntaxKind.None;

if (token.IsKind(SyntaxKind.OpenParenToken) &&
token.Parent.IsDelegateOrConstructorOrLocalFunctionOrMethodOrOperatorParameterList(includeOperators))
token.Parent is ParameterListSyntax parameterList1 &&
IsSuitableParameterList(parameterList1, includeOperators))
{
parameterIndex = 0;
return true;
Expand All @@ -1074,10 +1075,10 @@ public static bool IsParameterModifierContext(
}

if (token.IsKind(SyntaxKind.CommaToken) &&
token.Parent is ParameterListSyntax parameterList &&
parameterList.IsDelegateOrConstructorOrLocalFunctionOrMethodOrOperatorParameterList(includeOperators))
token.Parent is ParameterListSyntax parameterList2 &&
IsSuitableParameterList(parameterList2, includeOperators))
{
var commaIndex = parameterList.Parameters.GetWithSeparators().IndexOf(token);
var commaIndex = parameterList2.Parameters.GetWithSeparators().IndexOf(token);

parameterIndex = commaIndex / 2 + 1;
return true;
Expand All @@ -1094,34 +1095,42 @@ token.Parent is ParameterListSyntax parameterList &&

if (token.IsKind(SyntaxKind.CloseBracketToken) &&
token.Parent.IsKind(SyntaxKind.AttributeList) &&
token.Parent.Parent is ParameterSyntax parameter2 &&
parameter2.Parent is ParameterListSyntax parameterList2 &&
parameterList2.IsDelegateOrConstructorOrLocalFunctionOrMethodOrOperatorParameterList(includeOperators))
token.Parent.Parent is ParameterSyntax parameter3 &&
parameter3.Parent is ParameterListSyntax parameterList3 &&
IsSuitableParameterList(parameterList3, includeOperators))
{
parameterIndex = parameterList2.Parameters.IndexOf(parameter2);
parameterIndex = parameterList3.Parameters.IndexOf(parameter3);
return true;
}

ParameterSyntax? parameter3 = null;
ParameterSyntax? parameter4 = null;
if (token.Kind() is SyntaxKind.RefKeyword or SyntaxKind.InKeyword or SyntaxKind.ReadOnlyKeyword or SyntaxKind.OutKeyword or SyntaxKind.ThisKeyword or SyntaxKind.ParamsKeyword or SyntaxKind.ScopedKeyword)
{
parameter3 = token.Parent as ParameterSyntax;
parameter4 = token.Parent as ParameterSyntax;
previousModifier = token.Kind();
}
else if (token.IsKind(SyntaxKind.IdentifierToken) && token.Text == "scoped" && token.Parent is IdentifierNameSyntax scopedIdentifierName)
{
parameter3 = scopedIdentifierName.Parent as ParameterSyntax;
parameter4 = scopedIdentifierName.Parent as ParameterSyntax;
previousModifier = SyntaxKind.ScopedKeyword;
}

if (parameter3 is { Parent: ParameterListSyntax parameterList3 } &&
parameterList3.IsDelegateOrConstructorOrLocalFunctionOrMethodOrOperatorParameterList(includeOperators))
if (parameter4 is { Parent: ParameterListSyntax parameterList4 } &&
IsSuitableParameterList(parameterList4, includeOperators))
{
parameterIndex = parameterList3.Parameters.IndexOf(parameter3);
parameterIndex = parameterList4.Parameters.IndexOf(parameter4);
return true;
}

return false;

static bool IsSuitableParameterList(ParameterListSyntax parameterList, bool includeOperators)
=> parameterList.Parent switch
{
MethodDeclarationSyntax or LocalFunctionStatementSyntax or ConstructorDeclarationSyntax or DelegateDeclarationSyntax or TypeDeclarationSyntax => true,
OperatorDeclarationSyntax or ConversionOperatorDeclarationSyntax when includeOperators => true,
_ => false,
};
}

public static bool IsParamsModifierContext(
Expand Down Expand Up @@ -1185,11 +1194,8 @@ public static bool IsImplicitOrExplicitOperatorTypeContext(
public static bool IsParameterTypeContext(this SyntaxTree syntaxTree, int position, SyntaxToken tokenOnLeftOfPosition)
{
var token = tokenOnLeftOfPosition.GetPreviousTokenIfTouchingWord(position);

if (syntaxTree.IsParameterModifierContext(position, tokenOnLeftOfPosition, includeOperators: true, out _, out _))
{
return true;
}

// int this[ |
// int this[int i, |
Expand Down
Loading