Skip to content

Add a refactoring between namespace + nested module and root module - #20536

Open
xperiandri wants to merge 4 commits into
dotnet:mainfrom
xperiandri:feature/namespace-module-refactoring
Open

xperiandri wants to merge 4 commits into
dotnet:mainfrom
xperiandri:feature/namespace-module-refactoring

Conversation

@xperiandri

@xperiandri xperiandri commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Offers Ctrl+. on the header to turn namespace A.B with a single nested module C = into module A.B.C, and back. opens before the nested module move under the new header; the body is re-indented line by line, leaving multi-line strings alone.

Not offered when the namespace holds anything besides leading opens and the module, or when the file has a paired .fsi (the signature would stop matching, FS0240).

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

❗ Release notes required

You can open this PR in browser to add release notes: open in github.dev


✅ Found changes and release notes in following paths:

Change path Release notes path Description
`vsintegration/src` docs/release-notes/.VisualStudio/18.vNext.md

@xperiandri
xperiandri force-pushed the feature/namespace-module-refactoring branch from e51d4cd to 7863f7e Compare September 14, 2026 11:09
@xperiandri
xperiandri marked this pull request as ready for review September 14, 2026 19:40
@xperiandri
xperiandri requested a review from a team as a code owner September 14, 2026 19:40
xperiandri and others added 4 commits September 14, 2026 21:46
…ot-level module

With the caret on the header, 'namespace A.B' holding a single 'module C =' converts to 'module A.B.C', and 'module A.B.C' converts back. The compiler treats the two forms as the same module, so the edit only rewrites the header and moves the body by the nested module's indentation; lines inside multi-line string literals keep their text. Files with a signature file are not offered the conversion, because converting one side would unpair it from the other.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The namespace line and the opens were deleted as one block ending at the
first kept line, so a comment between the namespace and the opens left
the opens in place while copies were added under the new header. Each
of them is now deleted on its own, with the blank lines after it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e of its section

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@xperiandri
xperiandri force-pushed the feature/namespace-module-refactoring branch from 5f7ae33 to afc3127 Compare September 14, 2026 19:46
@github-actions github-actions Bot added the ⚠️ Affects-Design-Time Tooling check: PR touches type providers or dependency manager label Sep 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Tooling Safety Check — Affects-Design-Time
Affects-Design-Time: Modifies Visual Studio code executed while projects are open.

Generated by PR Tooling Safety Check · gpt56 1.8M ·

@T-Gro T-Gro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖🕵️ Please shorten the description using this guidance. Focus on the problem and why the change is needed, in simplified technical English. Leave the implementation inventory to the Files tab and retain necessary caveats.

@github-project-automation github-project-automation Bot moved this from New to In Progress in F# Compiler and Tooling Sep 15, 2026
@xperiandri xperiandri changed the title Refactoring to convert between a namespace with one nested module and a root-level module Add a refactoring between namespace + nested module and root module Sep 15, 2026
@xperiandri

Copy link
Copy Markdown
Contributor Author

Covered cases

Converts

  • namespace My.Company + module private Helpers =module private My.Company.Helpers, both directions, with the caret on the namespace or the module line; covers an XML doc comment, [<AutoOpen; RequireQualifiedAccess>], let inline and a multi-line triple-quoted string whose lines are not re-indented
  • rec on the namespace, the module or both: namespace rec A.B / module rec C =module rec A.B.C
  • A comment or XML doc comment before the nested module stays in front of the new header: // Helpers for B. above module A.B.C
  • #if DEBUG / #endif inside the body are dedented along with it
  • opens between the namespace and the module move below the new header: namespace A.B + open System + module C =module A.B.C followed by open System; also with several opens, a doc comment on the module, and a comment above the opens (it stays above the header and the opens are not left behind)
  • module A.B.Cnamespace A.B + module C = with the body indented and blank lines left empty
  • module rec A.B.Cmodule rec C =; header attributes and accessibility are kept: module [<AutoOpen>] internal A.B.Cmodule [<AutoOpen>] internal C =
  • Backticked namespace and a trailing header comment: module ``A-B``.C // headernamespace ``A-B`` + module C = // header
  • CRLF kept in both directions: namespace A.B\r\n\r\nmodule C =\r\n let x = 1\r\nmodule A.B.C\r\nlet x = 1\r\n
  • Round trip: module A.B.C converted to a nested module and back gives the original text

Not offered

  • The namespace holds more than one module (module C =module D =) or no module (type T = int)
  • namespace global with a nested module
  • A single-segment root module: module C
  • A module written as module C = begin … end
  • A comment after the namespace name: namespace A.B // B
  • Caret outside the header lines, e.g. on let x = 1, in either shape
  • An empty nested module: module C = with no declarations
  • An open after the module, or a declaration other than open before it (type T = int)
  • The implementation file has a signature file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚠️ Affects-Design-Time Tooling check: PR touches type providers or dependency manager

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants