提交 364f0567 编写于 作者: C CyrusNajmabadi

Strip inheritance nodes from outer types when we move a type to a new file.

上级 897028e9
......@@ -915,5 +915,34 @@ class Inner2
w.Options = w.Options.WithChangedOption(FormattingOptions.InsertFinalNewLine, false);
});
}
[WorkItem(16282, "https://github.com/dotnet/roslyn/issues/16282")]
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveTypeRemoveOuterInheritanceTypes()
{
var code =
@"
class Outer : IComparable {
[||]class Inner : IWhatever {
DateTime d;
}
}";
var codeAfterMove =
@"
partial class Outer : IComparable {
}";
var expectedDocumentName = "Inner.cs";
var destinationDocumentText =
@"
partial class Outer {
class Inner : IWhatever {
DateTime d;
}
}";
await TestMoveTypeToNewFileAsync(
code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
}
}
\ No newline at end of file
......@@ -180,5 +180,45 @@ End Class
"
Await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText)
End Function
<WorkItem(16282, "https://github.com/dotnet/roslyn/issues/16282")>
<WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)>
Public Async Function TestTypeInheritance() As Task
Dim code =
"
Class Outer
Inherits Something
Implements ISomething
[||]Class Inner
Inherits Other
Implements IOther
Sub M(d as DateTime)
End Sub
End Class
End Class
"
Dim codeAfterMove =
"
Partial Class Outer
Inherits Something
Implements ISomething
End Class"
Dim expectedDocumentName = "Inner.vb"
Dim destinationDocumentText =
"
Partial Class Outer
Class Inner
Inherits Other
Implements IOther
Sub M(d as DateTime)
End Sub
End Class
End Class"
Await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText)
End Function
End Class
End Namespace
\ No newline at end of file
......@@ -86,7 +86,8 @@ internal override async Task<ImmutableArray<CodeActionOperation>> GetOperationsA
// Make the type chain above this new type partial. Also, remove any
// attributes from the containing partial types. We don't want to create
// duplicate attributes on things.
AddPartialModifiersToTypeChain(documentEditor, removeAttributesAndComments: true);
AddPartialModifiersToTypeChain(
documentEditor, removeAttributesAndComments: true, removeTypeInheritance: true);
// remove things that are not being moved, from the forked document.
var membersToRemove = GetMembersToRemove(root);
......@@ -154,14 +155,15 @@ private async Task<SyntaxNode> AddFinalNewLineIfDesired(Document document, Synta
// Make the type chain above the type we're moving 'partial'.
// However, keep all the attributes on these types as theses are the
// original attributes and we don't want to mess with them.
AddPartialModifiersToTypeChain(documentEditor, removeAttributesAndComments: false);
AddPartialModifiersToTypeChain(documentEditor,
removeAttributesAndComments: false, removeTypeInheritance: false);
documentEditor.RemoveNode(State.TypeNode, SyntaxRemoveOptions.KeepNoTrivia);
var updatedDocument = documentEditor.GetChangedDocument();
// Now, remove any imports that we no longer need *if* they were used in the new
// file with the moved type. Essentially, those imports were here just to serve
// that new type and we shoudl remove them. If we have *other* imports that that
// that new type and we should remove them. If we have *other* imports that
// other file does not use *and* we do not use, we'll still keep those around.
// Those may be important to the user for code they're about to write, and we
// don't want to interfere with them by removing them.
......@@ -236,7 +238,9 @@ private static bool FilterToTopLevelMembers(SyntaxNode node, SyntaxNode typeNode
/// if a nested type is being moved, this ensures its containing type is partial.
/// </summary>
private void AddPartialModifiersToTypeChain(
DocumentEditor documentEditor, bool removeAttributesAndComments)
DocumentEditor documentEditor,
bool removeAttributesAndComments,
bool removeTypeInheritance)
{
var semanticFacts = State.SemanticDocument.Document.GetLanguageService<ISemanticFactsService>();
var typeChain = State.TypeNode.Ancestors().OfType<TTypeDeclarationSyntax>();
......@@ -255,6 +259,11 @@ private static bool FilterToTopLevelMembers(SyntaxNode node, SyntaxNode typeNode
documentEditor.RemoveAllAttributes(node);
documentEditor.RemoveAllComments(node);
}
if (removeTypeInheritance)
{
documentEditor.RemoveAllTypeInheritance(node);
}
}
documentEditor.ReplaceNode(State.TypeNode,
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Runtime.CompilerServices;
......@@ -1193,6 +1194,11 @@ private SyntaxNode WithAttributeLists(SyntaxNode declaration, SyntaxList<Attribu
}
}
internal override ImmutableArray<SyntaxNode> GetTypeInheritance(SyntaxNode declaration)
=> declaration is BaseTypeDeclarationSyntax baseType && baseType.BaseList != null
? ImmutableArray.Create<SyntaxNode>(baseType.BaseList)
: ImmutableArray<SyntaxNode>.Empty;
public override IReadOnlyList<SyntaxNode> GetNamespaceImports(SyntaxNode declaration)
{
switch (declaration.Kind())
......
......@@ -12,24 +12,19 @@ public static void SetAccessibility(this SyntaxEditor editor, SyntaxNode declara
}
public static void SetModifiers(this SyntaxEditor editor, SyntaxNode declaration, DeclarationModifiers modifiers)
{
editor.ReplaceNode(declaration, (d, g) => g.WithModifiers(d, modifiers));
}
=> editor.ReplaceNode(declaration, (d, g) => g.WithModifiers(d, modifiers));
internal static void RemoveAllAttributes(this SyntaxEditor editor, SyntaxNode declaration)
{
editor.ReplaceNode(declaration, (d, g) => g.RemoveAllAttributes(d));
}
=> editor.ReplaceNode(declaration, (d, g) => g.RemoveAllAttributes(d));
internal static void RemoveAllComments(this SyntaxEditor editor, SyntaxNode declaration)
{
editor.ReplaceNode(declaration, (d, g) => g.RemoveAllComments(d));
}
=> editor.ReplaceNode(declaration, (d, g) => g.RemoveAllComments(d));
internal static void RemoveAllTypeInheritance(this SyntaxEditor editor, SyntaxNode declaration)
=> editor.ReplaceNode(declaration, (d, g) => g.RemoveAllTypeInheritance(d));
public static void SetName(this SyntaxEditor editor, SyntaxNode declaration, string name)
{
editor.ReplaceNode(declaration, (d, g) => g.WithName(d, name));
}
=> editor.ReplaceNode(declaration, (d, g) => g.WithName(d, name));
public static void SetType(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode type)
{
......
......@@ -364,7 +364,7 @@ public SyntaxNode EventDeclaration(IEventSymbol symbol)
IEnumerable<SyntaxNode> removeAccessorStatements = null)
{
var invoke = symbol.Type.GetMembers("Invoke").FirstOrDefault(m => m.Kind == SymbolKind.Method) as IMethodSymbol;
var parameters = invoke != null ? invoke.Parameters.Select(p => this.ParameterDeclaration(p)) : null;
var parameters = invoke?.Parameters.Select(p => this.ParameterDeclaration(p));
return CustomEventDeclaration(
symbol.Name,
......@@ -548,7 +548,7 @@ public SyntaxNode Declaration(ISymbol symbol)
accessibility: type.DeclaredAccessibility,
modifiers: DeclarationModifiers.From(type),
baseType: TypeExpression(type.BaseType),
interfaceTypes: type.Interfaces != null ? type.Interfaces.Select(i => TypeExpression(i)) : null,
interfaceTypes: type.Interfaces.Select(i => TypeExpression(i)),
members: type.GetMembers().Where(CanBeDeclared).Select(m => Declaration(m)));
break;
case TypeKind.Struct:
......@@ -556,14 +556,14 @@ public SyntaxNode Declaration(ISymbol symbol)
type.Name,
accessibility: type.DeclaredAccessibility,
modifiers: DeclarationModifiers.From(type),
interfaceTypes: type.Interfaces != null ? type.Interfaces.Select(i => TypeExpression(i)) : null,
interfaceTypes: type.Interfaces.Select(i => TypeExpression(i)),
members: type.GetMembers().Where(CanBeDeclared).Select(m => Declaration(m)));
break;
case TypeKind.Interface:
declaration = InterfaceDeclaration(
type.Name,
accessibility: type.DeclaredAccessibility,
interfaceTypes: type.Interfaces != null ? type.Interfaces.Select(i => TypeExpression(i)) : null,
interfaceTypes: type.Interfaces.Select(i => TypeExpression(i)),
members: type.GetMembers().Where(CanBeDeclared).Select(m => Declaration(m)));
break;
case TypeKind.Enum:
......@@ -813,9 +813,7 @@ public SyntaxNode AttributeArgument(SyntaxNode expression)
/// Removes all attributes from the declaration, including return attributes.
/// </summary>
public SyntaxNode RemoveAllAttributes(SyntaxNode declaration)
{
return this.RemoveNodes(declaration, this.GetAttributes(declaration).Concat(this.GetReturnAttributes(declaration)));
}
=> this.RemoveNodes(declaration, this.GetAttributes(declaration).Concat(this.GetReturnAttributes(declaration)));
internal SyntaxNode RemoveAllComments(SyntaxNode declaration)
{
......@@ -825,6 +823,11 @@ internal SyntaxNode RemoveAllComments(SyntaxNode declaration)
internal abstract bool IsRegularOrDocComment(SyntaxTrivia trivia);
internal SyntaxNode RemoveAllTypeInheritance(SyntaxNode declaration)
=> this.RemoveNodes(declaration, this.GetTypeInheritance(declaration));
internal abstract ImmutableArray<SyntaxNode> GetTypeInheritance(SyntaxNode declaration);
/// <summary>
/// Gets the attributes of a declaration, not including the return attributes.
/// </summary>
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Composition
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editing
......@@ -1489,6 +1490,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return attr.WithTarget(Nothing)
End Function
Friend Overrides Function GetTypeInheritance(declaration As SyntaxNode) As ImmutableArray(Of SyntaxNode)
Dim typeDecl = TryCast(declaration, TypeBlockSyntax)
If typeDecl Is Nothing Then
Return ImmutableArray(Of SyntaxNode).Empty
End If
Dim builder = ArrayBuilder(Of SyntaxNode).GetInstance()
builder.AddRange(typeDecl.Inherits)
builder.AddRange(typeDecl.Implements)
Return builder.ToImmutableAndFree()
End Function
Public Overrides Function GetAttributes(declaration As SyntaxNode) As IReadOnlyList(Of SyntaxNode)
Return Me.Flatten(GetAttributeLists(declaration))
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册