diff --git a/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs b/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs index 1c8ce9b4691f96cd998ffa266fdf8bf3332b516f..e42358805676edd24f11035b94643796dd6109eb 100644 --- a/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs +++ b/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs @@ -33,7 +33,7 @@ class Z { int a; - public Z(int a) + public Z(int a{|Navigation:)|} { this.a = a; } @@ -56,7 +56,7 @@ class Z { int a; - public Z(int a) => this . a = a ; + public Z(int a{|Navigation:)|} => this . a = a ; }", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement)); } @@ -77,7 +77,7 @@ class Z { int a; - public Z(int a) => this . a = a ; + public Z(int a{|Navigation:)|} => this . a = a ; }", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement)); } @@ -100,7 +100,7 @@ class Z int a; int b; - public Z(int a, int b) + public Z(int a, int b{|Navigation:)|} { this . a = a ; this . b = b ; @@ -127,7 +127,7 @@ class Z int a; string b; - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { this.a = a; this.b = b; @@ -163,7 +163,7 @@ public Z(int a) this.a = a; } - public Z(string b) + public Z(string b{|Navigation:)|} { this.b = b; } @@ -198,7 +198,7 @@ public Z(int a) this.a = a; } - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { this.a = a; this.b = b; @@ -234,7 +234,7 @@ public Z(int a) this.a = a; } - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { this.a = a; this.b = b; @@ -270,7 +270,7 @@ public Z(int a) this.a = a; } - public Z(int a, string b) : this(a) + public Z(int a, string b{|Navigation:)|} : this(a) { this.b = b; } @@ -294,7 +294,7 @@ public Z(int a) this.a = a; } - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { this.a = a; this.b = b; @@ -313,7 +313,7 @@ public async Task TestMultipleProperties() }", @"class Z { - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { A = a; B = b; @@ -335,7 +335,7 @@ public async Task TestMultiplePropertiesWithQualification() }", @"class Z { - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { this.A = a; this.B = b; @@ -362,7 +362,7 @@ struct S { int i; - public S(int i) + public S(int i{|Navigation:)|} { this.i = i; } @@ -383,7 +383,7 @@ struct S struct S { - public S(int i) : this() + public S(int i{|Navigation:)|} : this() { this.i = i; } @@ -412,7 +412,7 @@ struct S int y; - public S(int y) : this() + public S(int y{|Navigation:)|} : this() { this.y = y; } @@ -439,7 +439,7 @@ struct S int y; - public S(int i) : this() + public S(int i{|Navigation:)|} : this() { this.i = i; } @@ -462,7 +462,7 @@ class Program { int i; - public Program(int i) + public Program(int i{|Navigation:)|} { this.i = i; } @@ -534,7 +534,7 @@ public async Task TestContextualKeywordName() { int yield; - public Program(int yield) + public Program(int yield{|Navigation:)|} { this.yield = yield; } @@ -577,7 +577,7 @@ class Z { (int, string) a; - public Z((int, string) a) + public Z((int, string) a{|Navigation:)|} { this.a = a; } @@ -597,7 +597,7 @@ public async Task TestUnderscoreInName1() { int _field; - public Program(int field) + public Program(int field{|Navigation:)|} { _field = field; } @@ -617,7 +617,7 @@ public async Task TestUnderscoreInName_PreferThis() { int _field; - public Program(int field) + public Program(int field{|Navigation:)|} { this._field = field; } @@ -637,7 +637,7 @@ public async Task TestGetter_Only_Auto_Props() }", @"abstract class Contribution { - public Contribution(string title, int number) + public Contribution(string title, int number{|Navigation:)|} { Title = title; Number = number; @@ -679,7 +679,7 @@ class Z { int a; - public Z(int a) + public Z(int a{|Navigation:)|} { this.a = a; } @@ -703,7 +703,7 @@ class Z { int a; - public Z(int a) + public Z(int a{|Navigation:)|} { this.a = a; } @@ -741,7 +741,7 @@ class Z { int a; - public Z() + public Z({|Navigation:)|} { } }", @@ -767,7 +767,7 @@ class Z int a; string b; - public Z(string b, int a) + public Z(string b, int a{|Navigation:)|} { this.b = b; this.a = a; @@ -799,7 +799,7 @@ class Z int a; string b; - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { this.a = a; this.b = b ?? throw new ArgumentNullException(nameof(b)); @@ -832,7 +832,7 @@ class Z int a; string b; - public Z(int a, string b) + public Z(int a, string b{|Navigation:)|} { if (b == null) { @@ -897,6 +897,30 @@ public void M() } public void N() { } +}"); + } + + [WorkItem(21067, "https://github.com/dotnet/roslyn/pull/21067")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructorFromMembers)] + public async Task TestFinalCaretPosition() + { + await TestInRegularAndScriptAsync( +@"using System.Collections.Generic; + +class Z +{ + [|int a;|] +}", +@"using System.Collections.Generic; + +class Z +{ + int a; + + public Z(int a{|Navigation:)|} + { + this.a = a; + } }"); } } diff --git a/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs b/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs index 553c4b6b42cd379ba7dc22e1fd14e07dd94b79cf..5921cb60f5a887d52d4d97cba5490ea92ad10de6 100644 --- a/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs +++ b/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs @@ -176,7 +176,7 @@ internal class CodeActionEditHandlerService : ForegroundThreadAffinitizedObject, } var updatedSolution = operations.OfType().FirstOrDefault()?.ChangedSolution ?? oldSolution; - TryStartRenameSession(workspace, oldSolution, updatedSolution, cancellationToken); + TryNavigateToLocationOrStartRenameSession(workspace, oldSolution, updatedSolution, cancellationToken); } private TextDocument TryGetSingleChangedText( @@ -259,7 +259,7 @@ internal class CodeActionEditHandlerService : ForegroundThreadAffinitizedObject, } } - private void TryStartRenameSession(Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) + private void TryNavigateToLocationOrStartRenameSession(Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) { var changedDocuments = newSolution.GetChangedDocuments(oldSolution); foreach (var documentId in changedDocuments) @@ -272,9 +272,16 @@ private void TryStartRenameSession(Workspace workspace, Solution oldSolution, So var root = document.GetSyntaxRootSynchronously(cancellationToken); - var renameTokenOpt = root.GetAnnotatedNodesAndTokens(RenameAnnotation.Kind) - .Where(s => s.IsToken) - .Select(s => s.AsToken()) + var navigationTokenOpt = root.GetAnnotatedTokens(NavigationAnnotation.Kind) + .FirstOrNullable(); + if (navigationTokenOpt.HasValue) + { + var navigationService = workspace.Services.GetService(); + navigationService.TryNavigateToPosition(workspace, documentId, navigationTokenOpt.Value.SpanStart); + return; + } + + var renameTokenOpt = root.GetAnnotatedTokens(RenameAnnotation.Kind) .FirstOrNullable(); if (renameTokenOpt.HasValue) diff --git a/src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs b/src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs index 2519671ea97e9133f88b1e005255841f34b67195..c2223f273f9c7a6c1c5a24156acf87112a5db169 100644 --- a/src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs +++ b/src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.ChangeSignature; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using Xunit; @@ -39,9 +40,11 @@ protected override ParseOptions GetScriptOptions() var codeIssueOrRefactoring = await GetCodeRefactoringAsync(workspace, testOptions); await TestActionsAsync(workspace, expectedCode, index, codeIssueOrRefactoring.Actions, - conflictSpans: ImmutableArray.Empty, - renameSpans: ImmutableArray.Empty, - warningSpans: ImmutableArray.Empty, ignoreTrivia: true); + conflictSpans: ImmutableArray.Empty, + renameSpans: ImmutableArray.Empty, + warningSpans: ImmutableArray.Empty, + navigationSpans: ImmutableArray.Empty, + ignoreTrivia: true); } } else diff --git a/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index 09ccfc5b291a216c0edcc9394ed820b6cce0a0a4..ba28a1985b8d1d47202b565e2f1c7c56964d6e78 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -364,11 +364,13 @@ public TestParameters WithFixProviderData(object fixProviderData) TestParameters parameters) { MarkupTestFile.GetSpans( - expectedMarkup.NormalizeLineEndings(), out var expected, out IDictionary> spanMap); + expectedMarkup.NormalizeLineEndings(), + out var expected, out IDictionary> spanMap); var conflictSpans = spanMap.GetOrAdd("Conflict", _ => ImmutableArray.Empty); var renameSpans = spanMap.GetOrAdd("Rename", _ => ImmutableArray.Empty); var warningSpans = spanMap.GetOrAdd("Warning", _ => ImmutableArray.Empty); + var navigationSpans = spanMap.GetOrAdd("Navigation", _ => ImmutableArray.Empty); using (var workspace = CreateWorkspaceFromOptions(initialMarkup, parameters)) { @@ -380,7 +382,7 @@ public TestParameters WithFixProviderData(object fixProviderData) await TestActionsAsync( workspace, expected, index, actions, - conflictSpans, renameSpans, warningSpans, + conflictSpans, renameSpans, warningSpans, navigationSpans, ignoreTrivia: ignoreTrivia, parseOptions: parameters.parseOptions, priority: priority); @@ -393,12 +395,15 @@ public TestParameters WithFixProviderData(object fixProviderData) ImmutableArray conflictSpans, ImmutableArray renameSpans, ImmutableArray warningSpans, + ImmutableArray navigationSpans, bool ignoreTrivia, ParseOptions parseOptions = null, CodeActionPriority? priority = null) { var operations = await VerifyInputsAndGetOperationsAsync(index, actions, priority); - return await TestOperationsAsync(workspace, expected, operations, conflictSpans, renameSpans, warningSpans, ignoreTrivia, expectedChangedDocumentId: null, parseOptions: parseOptions); + return await TestOperationsAsync( + workspace, expected, operations, conflictSpans, renameSpans, + warningSpans, navigationSpans, ignoreTrivia, expectedChangedDocumentId: null, parseOptions: parseOptions); } protected async Task> TestOperationsAsync( @@ -408,6 +413,7 @@ public TestParameters WithFixProviderData(object fixProviderData) ImmutableArray conflictSpans, ImmutableArray renameSpans, ImmutableArray warningSpans, + ImmutableArray navigationSpans, bool ignoreTrivia, DocumentId expectedChangedDocumentId, ParseOptions parseOptions = null) @@ -439,6 +445,7 @@ public TestParameters WithFixProviderData(object fixProviderData) TestAnnotations(conflictSpans, ConflictAnnotation.Kind); TestAnnotations(renameSpans, RenameAnnotation.Kind); TestAnnotations(warningSpans, WarningAnnotation.Kind); + TestAnnotations(navigationSpans, NavigationAnnotation.Kind); return Tuple.Create(oldSolution, newSolution); diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs b/src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs index ed24a72079101f5fb615a9f910cf25d2492f6314..ce2a4bb1baffae4a399aa55861f0eb6c0038dc1c 100644 --- a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs +++ b/src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs @@ -372,6 +372,7 @@ protected Document GetDocumentAndAnnotatedSpan(TestWorkspace workspace, out stri conflictSpans: ImmutableArray.Empty, renameSpans: ImmutableArray.Empty, warningSpans: ImmutableArray.Empty, + navigationSpans: ImmutableArray.Empty, ignoreTrivia: false, expectedChangedDocumentId: testState.ExistingDocument.Id); } else @@ -393,7 +394,9 @@ protected Document GetDocumentAndAnnotatedSpan(TestWorkspace workspace, out stri await TestOperationsAsync(testState.Workspace, expectedTextWithUsings, operations, conflictSpans: ImmutableArray.Empty, renameSpans: ImmutableArray.Empty, - warningSpans: ImmutableArray.Empty, ignoreTrivia: false, + warningSpans: ImmutableArray.Empty, + navigationSpans: ImmutableArray.Empty, + ignoreTrivia: false, expectedChangedDocumentId: testState.InvocationDocument.Id); } diff --git a/src/EditorFeatures/TestUtilities/MoveType/AbstractMoveTypeTest.cs b/src/EditorFeatures/TestUtilities/MoveType/AbstractMoveTypeTest.cs index 70d174dd823cb0d8190dd8dceed992e9413962f5..10dc17e228ce61e558feee3f516f868ae8be0317 100644 --- a/src/EditorFeatures/TestUtilities/MoveType/AbstractMoveTypeTest.cs +++ b/src/EditorFeatures/TestUtilities/MoveType/AbstractMoveTypeTest.cs @@ -137,6 +137,7 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa conflictSpans: ImmutableArray.Empty, renameSpans: ImmutableArray.Empty, warningSpans: ImmutableArray.Empty, + navigationSpans: ImmutableArray.Empty, ignoreTrivia: ignoreTrivia, expectedChangedDocumentId: null); } diff --git a/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb b/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb index 97e04c12747fb3ef43c206776842250a83a2e62b..1d9a9e3319f3c72405948a9e57c4e5666c45a25e 100644 --- a/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb +++ b/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb @@ -21,7 +21,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.GenerateConstructo End Class", "Class Program Private i As Integer - Public Sub New(i As Integer) + Public Sub New(i As Integer{|Navigation:)|} Me.i = i End Sub End Class") @@ -37,7 +37,7 @@ End Class", "Class Program Private i As Integer Private b As String - Public Sub New(i As Integer, b As String) + Public Sub New(i As Integer, b As String{|Navigation:)|} Me.i = i Me.b = b End Sub @@ -60,7 +60,7 @@ End Class", Public Sub New(i As Integer) Me.i = i End Sub - Public Sub New(b As String) + Public Sub New(b As String{|Navigation:)|} Me.b = b End Sub End Class") @@ -82,7 +82,7 @@ End Class", Public Sub New(i As Integer) Me.i = i End Sub - Public Sub New(i As Integer, b As String) + Public Sub New(i As Integer, b As String{|Navigation:)|} Me.i = i Me.b = b End Sub @@ -113,7 +113,7 @@ End Class") End Structure", "Structure S Private i As Integer - Public Sub New(i As Integer) + Public Sub New(i As Integer{|Navigation:)|} Me.i = i End Sub End Structure") @@ -127,7 +127,7 @@ End Structure") End Class", "Class Program(Of T) Private i As Integer - Public Sub New(i As Integer) + Public Sub New(i As Integer{|Navigation:)|} Me.i = i End Sub End Class") @@ -150,7 +150,7 @@ End Class", Public Sub New(i As Integer) Me.i = i End Sub - Public Sub New(i As Integer, b As String) + Public Sub New(i As Integer, b As String{|Navigation:)|} Me.New(i) Me.b = b End Sub @@ -167,7 +167,7 @@ index:=1) Public Property B As String|] End Class", "Class Z - Public Sub New(a As Integer, b As String) + Public Sub New(a As Integer, b As String{|Navigation:)|} Me.A = a Me.B = b End Sub @@ -185,7 +185,7 @@ End Class") ReadOnly Property Number As Integer|] End Class", "Class Contribution - Public Sub New(title As String, number As Integer) + Public Sub New(title As String, number As Integer{|Navigation:)|} Me.Title = title Me.Number = number End Sub @@ -214,7 +214,7 @@ End Class") End Class", "Class Program Private i As Integer - Public Sub New(i As Integer) + Public Sub New(i As Integer{|Navigation:)|} Me.i = i End Sub End Class", chosenSymbols:={"i"}) @@ -229,7 +229,7 @@ End Class", chosenSymbols:={"i"}) End Class", "Class Program Private i As Integer - Public Sub New() + Public Sub New({|Navigation:)|} End Sub End Class", chosenSymbols:={}) End Function @@ -245,7 +245,7 @@ End Class", "Class Program Private i As Integer Private j As String - Public Sub New(j As String, i As Integer) + Public Sub New(j As String, i As Integer{|Navigation:)|} Me.j = j Me.i = i End Sub @@ -260,7 +260,7 @@ End Class", chosenSymbols:={"j", "i"}) End Class", "Class Program Private i As Integer - Public Sub New(i As Integer) + Public Sub New(i As Integer{|Navigation:)|} Me.i = i End Sub End Class", chosenSymbols:={"i"}) diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/ConstructorDelegatingCodeAction.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/ConstructorDelegatingCodeAction.cs index 621dbacd50c9315e28f9235fe6e5e4fa713283bf..a1b18b13dbbedbaefc32298f4e9d315544631bec 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/ConstructorDelegatingCodeAction.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/ConstructorDelegatingCodeAction.cs @@ -103,7 +103,7 @@ protected override async Task GetChangedDocumentAsync(CancellationToke afterThisLocation: afterThisLocation), cancellationToken: cancellationToken).ConfigureAwait(false); - return result; + return await AddNavigationAnnotationAsync(result, cancellationToken).ConfigureAwait(false); } public override string Title diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/FieldDelegatingCodeAction.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/FieldDelegatingCodeAction.cs index 478173b6dca77a7499e23c74fa1ce1f34553671d..d06abae020db36e1add67b1538f0da375bc0ef5a 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/FieldDelegatingCodeAction.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/FieldDelegatingCodeAction.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -84,7 +85,7 @@ protected override async Task GetChangedDocumentAsync(CancellationToke afterThisLocation: afterThisLocation), cancellationToken).ConfigureAwait(false); - return result; + return await AddNavigationAnnotationAsync(result, cancellationToken).ConfigureAwait(false); } public override string Title diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersCodeRefactoringProvider.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersCodeRefactoringProvider.cs index 0c4f0aacdda8212f18ca9b4e94e6c3ec849f042a..795107dea83875425e68ed4e48bf337e389d1b71 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersCodeRefactoringProvider.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.GenerateFromMembers; using Microsoft.CodeAnalysis.Internal.Log; @@ -165,5 +166,26 @@ private ImmutableArray GetCodeActions(Document document, State state return result.ToImmutableAndFree(); } + + private static async Task AddNavigationAnnotationAsync(Document document, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + + var nodes = root.GetAnnotatedNodes(CodeGenerator.Annotation); + var syntaxFacts = document.GetLanguageService(); + + foreach (var node in nodes) + { + var parameterList = syntaxFacts.GetParameterList(node); + if (parameterList != null) + { + var closeParen = parameterList.GetLastToken(); + var newRoot = root.ReplaceToken(closeParen, closeParen.WithAdditionalAnnotations(NavigationAnnotation.Create())); + return document.WithSyntaxRoot(newRoot); + } + } + + return document; + } } } diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index 00354c091d65103cddd03b43a3a8a54b5dd25b41..d16b439d261e070a77f2331273cda60a8787e252 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -2610,7 +2610,7 @@ public override SyntaxToken VisitToken(SyntaxToken token) } } - private static BaseParameterListSyntax GetParameterList(SyntaxNode declaration) + internal static BaseParameterListSyntax GetParameterList(SyntaxNode declaration) { switch (declaration.Kind()) { diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs index 729f52121c38d1d38a3cba1df7422618ed1a4ed0..e1ebf40f3ad553c9a92fb02460ef35ad1ad7402e 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs +++ b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -207,6 +208,9 @@ public bool IsNamedParameter(SyntaxNode node) public SyntaxNode GetDefaultOfParameter(SyntaxNode node) => (node as ParameterSyntax)?.Default; + public SyntaxNode GetParameterList(SyntaxNode node) + => CSharpSyntaxGenerator.GetParameterList(node); + public bool IsSkippedTokensTrivia(SyntaxNode node) { return node is SkippedTokensTriviaSyntax; diff --git a/src/Workspaces/Core/Portable/CodeActions/Annotations/ConflictAnnotation.cs b/src/Workspaces/Core/Portable/CodeActions/Annotations/ConflictAnnotation.cs index 0c8e34fce9a0ebbb5e17a844d00a93ea68329cfe..7dedf83be7d7e79d242ffb0ca730ce8964a2586b 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Annotations/ConflictAnnotation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Annotations/ConflictAnnotation.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - namespace Microsoft.CodeAnalysis.CodeActions { /// diff --git a/src/Workspaces/Core/Portable/CodeActions/Annotations/NavigationAnnotation.cs b/src/Workspaces/Core/Portable/CodeActions/Annotations/NavigationAnnotation.cs new file mode 100644 index 0000000000000000000000000000000000000000..b72e5343a57796dc2778db395fdd76d79fc9198d --- /dev/null +++ b/src/Workspaces/Core/Portable/CodeActions/Annotations/NavigationAnnotation.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.CodeActions +{ + /// + /// Apply this annotation to an appropriate Syntax element to request that it should be + /// navigated to by the user after the action. + /// + internal static class NavigationAnnotation + { + public const string Kind = "CodeAction_Navigation"; + + public static SyntaxAnnotation Create() + => new SyntaxAnnotation(Kind); + } +} diff --git a/src/Workspaces/Core/Portable/CodeActions/Annotations/RenameAnnotation.cs b/src/Workspaces/Core/Portable/CodeActions/Annotations/RenameAnnotation.cs index 0d4e103e16effc7154cc986f378a005cd28a445f..0010779038ddd87fea92643b8dacd345cd110ea2 100644 --- a/src/Workspaces/Core/Portable/CodeActions/Annotations/RenameAnnotation.cs +++ b/src/Workspaces/Core/Portable/CodeActions/Annotations/RenameAnnotation.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - namespace Microsoft.CodeAnalysis.CodeActions { /// diff --git a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationHelpers.cs b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationHelpers.cs index 3396ea40380a2a2b575810943ef784a013916228..b1f9f6144e7a5b74fa0d66614674b45d7d5c4cbd 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationHelpers.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationHelpers.cs @@ -49,7 +49,7 @@ public static TSyntaxNode AddAnnotationsTo(ISymbol symbol, TSyntaxN public static TSyntaxNode AddCleanupAnnotationsTo(TSyntaxNode node) where TSyntaxNode : SyntaxNode { - return node.WithAdditionalAnnotations(Formatter.Annotation); + return node.WithAdditionalAnnotations(Formatter.Annotation, CodeGenerator.Annotation); } public static void CheckNodeType(SyntaxNode node, string argumentName) @@ -215,9 +215,9 @@ public static T GetReuseableSyntaxNodeForSymbol(ISymbol symbol, CodeGeneratio { Contract.ThrowIfNull(symbol); - return options != null && options.ReuseSyntax && symbol.DeclaringSyntaxReferences.Length == 1 ? - symbol.DeclaringSyntaxReferences[0].GetSyntax() as T : - null; + return options != null && options.ReuseSyntax && symbol.DeclaringSyntaxReferences.Length == 1 + ? symbol.DeclaringSyntaxReferences[0].GetSyntax() as T + : null; } public static T GetReuseableSyntaxNodeForAttribute(AttributeData attribute, CodeGenerationOptions options) diff --git a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerator.cs b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerator.cs index 794f0d449187428f49cc9c83b45851b7d3b8cc16..eeb7526aa6ecb3500fb515fb18c2c58ff0fc7338 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerator.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerator.cs @@ -11,6 +11,11 @@ namespace Microsoft.CodeAnalysis.CodeGeneration /// internal static class CodeGenerator { + /// + /// Annotation placed on generated syntax. + /// + public static readonly SyntaxAnnotation Annotation = new SyntaxAnnotation(nameof(CodeGenerator)); + private static ICodeGenerationService GetCodeGenerationService(Workspace workspace, string language) { return workspace.Services.GetLanguageServices(language).GetService(); diff --git a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs index 0bc087ef1357ad04fc675bbd6f8ad4addbf58125..2b34bbeaf934d4be893a2c82acaa6d294cb454e9 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs @@ -132,6 +132,7 @@ internal interface ISyntaxFactsService : ILanguageService bool IsNamedParameter(SyntaxNode node); SyntaxNode GetDefaultOfParameter(SyntaxNode node); + SyntaxNode GetParameterList(SyntaxNode node); bool IsSkippedTokensTrivia(SyntaxNode node); diff --git a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb index 3afc9289d9ce12de172b4bbaee08218c73ffa907..361e120e98c35f5e2f22bf429c57a8ac17342167 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb @@ -3063,7 +3063,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration statement.CaseBlocks.InsertRange(index, switchSections.Cast(Of CaseBlockSyntax))) End Function - Private Function GetParameterList(declaration As SyntaxNode) As ParameterListSyntax + Friend Shared Function GetParameterList(declaration As SyntaxNode) As ParameterListSyntax Select Case declaration.Kind Case SyntaxKind.SubBlock, SyntaxKind.FunctionBlock diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb index a6d6159ef9a7bf578a745d618a3dde1e4cad2091..0ad08fd1fed74bb6e1f1e5d652a6d2084b18ae47 100644 --- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb +++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb @@ -10,6 +10,7 @@ Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text +Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts @@ -202,6 +203,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return TryCast(node, ParameterSyntax)?.Default End Function + Public Function GetParameterList(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetParameterList + Return VisualBasicSyntaxGenerator.GetParameterList(node) + End Function + Public Function IsSkippedTokensTrivia(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsSkippedTokensTrivia Return TypeOf node Is SkippedTokensTriviaSyntax End Function