Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 14, 2025

Summary

Fixes #60698

This PR adds support for renaming files that follow the Outer.Inner.cs naming convention when renaming nested types. Previously, when renaming a nested type in a file named using this convention, the IDE did not offer to rename the file. This is a common pattern used throughout the Roslyn codebase and in many .NET projects for organizing nested types.

Problem

When you have a file like Outer.Inner.cs containing:

partial class Outer
{
    class Inner {}
}

And you invoke rename on the Inner symbol, the rename dialog did not offer to rename the file. Similarly, renaming Outer would not suggest updating the filename.

Solution

This PR enhances the rename infrastructure to:

  1. Detect nested type patterns - Recognize when a type's containment hierarchy matches a document name (e.g., type Inner inside Outer matches file Outer.Inner.cs)
  2. Support multi-level nesting - Handle files like A.B.C.cs for three or more levels of nesting
  3. Generate correct new names - When renaming any type in the hierarchy, produce the appropriate new filename

Examples

Renaming the inner type:

  • File: Outer.Inner.csOuter.Foo.cs
  • Code: class Innerclass Foo

Renaming the outer type:

  • File: Outer.Inner.csBar.Inner.cs
  • Code: class Outerclass Bar

Multi-level nesting:

  • File: A.B.C.csA.X.C.cs
  • Code: class Bclass X (middle type renamed)

Implementation Details

WorkspacePathUtilities.cs

Added three new methods to support nested type matching:

  • SymbolMatchesDocumentName() - Checks if a symbol's full type hierarchy matches the document name pattern
  • GetTypeHierarchy() - Extracts the containment chain from outermost to innermost type
  • GetNewDocumentNameForSymbolRename() - Generates the new filename when a type in the hierarchy is renamed

AbstractEditorInlineRenameService.SymbolRenameInfo.cs

Enhanced GetFileRenameInfo() to check for nested type patterns in addition to simple type names, returning InlineRenameFileRenameInfo.Allowed when a match is found.

Renamer.RenameSymbolDocumentAction.cs

Updated GetMatchingTypeDeclarationAsync() and AnalyzeAsync() to find and match nested types with document names. Optimized to only create semantic models when the document name contains dots (indicating potential nested types).

Testing

Added six comprehensive test cases in CSharpRenamerTests.cs covering:

  • Renaming inner types
  • Renaming outer types
  • Three-level nesting
  • Renaming middle types in hierarchies
  • Edge cases (non-matching names, types with namespaces)

Technical Considerations

  • Performance: Fast path for simple types (no semantic model needed). Semantic model only created when document name suggests nested types.
  • Compatibility: Case-insensitive matching maintains existing behavior. Works across all target frameworks (netstandard2.0, net8.0, net9.0).
  • Symbol comparison: Uses SymbolEqualityComparer.Default for proper symbol equality checks.
  • No breaking changes: Existing simple type rename behavior is preserved.
Original prompt

This section details on the original issue you should resolve

<issue_title>Renaming a nested type should offer to update filename using Outer.Inner.cs convention</issue_title>
<issue_description>Version Used: 17.2.0 Preview 3.0 [32308.589.main]

Steps to Reproduce:

Create a file Outer.Inner.cs containing:

partial class Outer
{
    class Inner {}
}

Invoke rename on the Inner symbol.

Notice that the rename dialog does not offer to rename the file.

image

Expected Behavior:

Renaming Inner to Foo also renames the source file to Outer.Foo.cs.

Equally, renaming Outer to Bar further renames the file to Bar.Foo.cs (and renames any other files with the same prefix that have corresponding nested types).

Equally files nested three or more levels deep should support this A.B.C.cs convention.

Actual Behavior:

Rename for the file is disabled.</issue_description>

Comments on the Issue (you are @copilot in this section)

@CyrusNajmabadi We should detect and support updating both cases. Both are things that people do. The metadata name may be Outer+Inner, but teh C#/VB names are certainly Outer.Inner, so its' totally reasonable for people to do that (and we see it in our own code and in devdiv for sure :)).

Fixes #60054


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@Copilot Copilot AI changed the title [WIP] Add file renaming support for nested types Add support for renaming nested types with Outer.Inner.cs file naming convention Oct 15, 2025
@Copilot Copilot AI requested a review from akhera99 October 15, 2025 00:06
Copilot finished work on behalf of akhera99 October 15, 2025 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Renaming a nested type should offer to update filename using Outer.Inner.cs convention

2 participants