Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 10, 2025

Fix incorrect open statement placement for modules with multiline attributes

Plan

  • Part 1: Fix root cause in ServiceParsedInputOps.fs
    • Update walkSynModuleDecl to use trivia.ModuleKeyword for correct line detection (nested modules)
    • Update walkSynModuleOrNamespace to use trivia.LeadingKeyword for correct line detection (top-level modules)
    • Fix namespace handling to preserve original startLine - 1 behavior
  • Part 2: Update AddOpenCodeFixProvider.fs
    • Remove multiline attribute workaround (lines 57-75)
    • Keep logic for implicit modules and other edge cases
  • Part 3: Add tests
    • Add test in AddOpenOnTopOffTests.fs for multiline attributes
    • Add test in AddOpenOnTopOnTests.fs for multiline attributes
    • Fix test expectation for AlwaysPlaceOpensAtTopLevel mode
  • Add release notes
    • FSharp.Compiler.Service/11.0.0.md
    • VisualStudio/18.0.md
  • Run AddOpen tests to verify no regressions
  • Verify all changes work correctly

Changes Made

  1. ServiceParsedInputOps.fs:
    • Modified walkSynModuleDecl to use trivia.ModuleKeyword.StartLine for nested modules
    • Modified walkSynModuleOrNamespace to use trivia.LeadingKeyword range for top-level modules and namespaces
    • For modules: use keyword line directly
    • For namespaces: use keyword line - 1 (preserving original behavior)
    • Both changes exclude attributes from the start line calculation
  2. AddOpenCodeFixProvider.fs: Removed multiline attribute workaround (lines 57-75) while keeping implicit module handling
  3. Tests: Added multiline attribute tests to both test files
    • Fixed expectation for AddOpenOnTopOnTests to place open at namespace level (grouping with existing opens) when AlwaysPlaceOpensAtTopLevel = true
  4. Release notes: Added entries to FSharp.Compiler.Service/11.0.0.md and VisualStudio/18.0.md

Fix Details

The initial fix only handled nested modules, causing test failures. Second iteration fixed top-level modules but broke namespace handling. The namespace case requires startLine - 1 instead of using the keyword line directly. Test expectation was corrected to match the behavior of AlwaysPlaceOpensAtTopLevel = true, which places opens at the namespace level when there are existing opens there (grouping behavior).

Fixes #18671

Original prompt

Fix incorrect open statement placement for modules with multiline attributes

Problem

When using the "Add open" code fix on modules with multiline attributes, the open statement is incorrectly inserted inside the attribute block instead of after the module declaration.

Current Buggy Behavior:

[<RequireQualifiedAccess;
  CompiledName((nameof System.Collections.Immutable.ImmutableArray)
    open System.Collections.Generic  // ❌ WRONG - inserted here
               + "Module")>]
module FlatList =
    let a : KeyValuePair<string, int> = ...

Expected Behavior:

[<RequireQualifiedAccess;
  CompiledName((nameof System.Collections.Immutable.ImmutableArray)
               + "Module")>]
module FlatList =
    open System.Collections.Generic  // ✅ CORRECT - should be here
    let a : KeyValuePair<string, int> = ...

Root Cause

The compiler service in src/Compiler/Service/ServiceParsedInputOps.fs returns incorrect insertion context for modules with multiline attributes. The AddOpenCodeFixProvider has a workaround hack to patch this, but it only handles single-line attributes.

Solution - Two-Part Fix

Part 1: Fix Root Cause in Compiler Service

File: src/Compiler/Service/ServiceParsedInputOps.fs
Location: Around line 2461 in the walkSynModuleDecl function

Current Code:

| SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = ident); decls = decls; range = range) ->
    let fullIdent = parent @ ident
    let startLine = range.StartLine - 1
    
    let moduleBodyIndentation =
        getMinColumn decls |> Option.defaultValue (range.StartColumn + 4)

    doRange NestedModule fullIdent range.StartLine moduleBodyIndentation
    List.iter (walkSynModuleDecl fullIdent) decls

Replace With:

| SynModuleDecl.NestedModule(
    moduleInfo = SynComponentInfo(longId = ident); 
    decls = decls; 
    range = range;
    trivia = trivia) ->
    
    let fullIdent = parent @ ident
    
    // Use trivia to get the actual module keyword line, which excludes attributes
    let moduleKeywordLine = 
        match trivia.ModuleKeyword with
        | Some moduleKeywordRange -> moduleKeywordRange.StartLine
        | None -> range.StartLine  // Fallback if trivia unavailable
    
    let startLine = moduleKeywordLine - 1
    
    let moduleBodyIndentation =
        getMinColumn decls |> Option.defaultValue (range.StartColumn + 4)

    doRange NestedModule fullIdent moduleKeywordLine moduleBodyIndentation
    List.iter (walkSynModuleDecl fullIdent) decls

Explanation: The issue is that range.StartLine includes attributes. By using trivia.ModuleKeyword.StartLine, we get the exact line where the module keyword appears, skipping all attributes regardless of how many lines they span.

Part 2: Simplify AddOpenCodeFixProvider (Remove Workaround)

File: vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs
Location: Lines 33-88, the getOpenDeclaration function

Current Code (with hack comments):

// Hey, I know what you're thinking: this is a horrible hack.
// Indeed it is, this is a better (but still bad) version of the OpenDeclarationHelper.
// The things should be actually fixed in the InsertionContext, it's bugged.
// But currently CompletionProvider also depends on InsertionContext and it's not tested enough.
// So fixing InsertionContext or OpenDeclarationHelper might break completion which would be bad.
// The hack below is at least heavily tested.
// And at least it shows what should be fixed down the line.
let getOpenDeclaration (sourceText: SourceText) (ctx: InsertionContext) (ns: string) =
    // insertion context counts from 2, make the world sane
    let insertionLineNumber = ctx.Pos.Line - 2
    let margin = String(' ', ctx.Pos.Column)

    let startLineNumber, openDeclaration =
        match ctx.ScopeKind with
        | ScopeKind.TopModule ->
            match sourceText.Lines[insertionLineNumber].ToString().Trim() with

            // explicit top level module
            | line when line.StartsWith "module" && not (line.EndsWith "=") -> insertionLineNumber + 2, $"{margin}open {ns}{br}{br}"

            // nested module, shouldn't be here
            | line when line.StartsWith "module" -> insertionLineNumber, $"{margin}open {ns}{br}{br}"

            // attribute, shouldn't be here
            | line when line.StartsWith "[<" && line.EndsWith ">]" ->
                let moduleDeclLineNumberOpt =
                    sourceText.Lines
                    |> Seq.skip insertionLineNumber
                    |> Seq.tryFindIndex (fun line -> line.ToString().Contains "module")

                match moduleDeclLineNumberOpt with
                // implicit top level module
                | None -> insertionLineNumber, $"{margin}open {ns}{br}{br}"
                // explicit top level module
                | Some number ->
                    // add back the skipped lines...

</details>

*This pull request was created as a result of the following prompt from Copilot chat.*
> Fix incorrect `open` statement placement for modules with multiline attributes
> 
> ## Problem
> When using the "Add open" code fix on modules with multiline attributes, the `open` statement is incorrectly inserted inside the attribute block instead of after the module declaration.
> 
> **Current Buggy Behavior:**
> ```fsharp
> [<RequireQualifiedAccess;
>   CompiledName((nameof System.Collections.Immutable.ImmutableArray)
>     open System.Collections.Generic  // ❌ WRONG - inserted here
>                + "Module")>]
> module FlatList =
>     let a : KeyValuePair<string, int> = ...
> ```
> 
> **Expected Behavior:**
> ```fsharp
> [<RequireQualifiedAccess;
>   CompiledName((nameof System.Collections.Immutable.ImmutableArray)
>                + "Module")>]
> module FlatList =
>     open System.Collections.Generic  // ✅ CORRECT - should be here
>     let a : KeyValuePair<string, int> = ...
> ```
> 
> ## Root Cause
> The compiler service in `src/Compiler/Service/ServiceParsedInputOps.fs` returns incorrect insertion context for modules with multiline attributes. The `AddOpenCodeFixProvider` has a workaround hack to patch this, but it only handles single-line attributes.
> 
> ## Solution - Two-Part Fix
> 
> ### Part 1: Fix Root Cause in Compiler Service
> 
> **File:** `src/Compiler/Service/ServiceParsedInputOps.fs`
> **Location:** Around line 2461 in the `walkSynModuleDecl` function
> 
> **Current Code:**
> ```fsharp
> | SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = ident); decls = decls; range = range) ->
>     let fullIdent = parent @ ident
>     let startLine = range.StartLine - 1
>     
>     let moduleBodyIndentation =
>         getMinColumn decls |> Option.defaultValue (range.StartColumn + 4)
> 
>     doRange NestedModule fullIdent range.StartLine moduleBodyIndentation
>     List.iter (walkSynModuleDecl fullIdent) decls
> ```
> 
> **Replace With:**
> ```fsharp
> | SynModuleDecl.NestedModule(
>     moduleInfo = SynComponentInfo(longId = ident); 
>     decls = decls; 
>     range = range;
>     trivia = trivia) ->
>     
>     let fullIdent = parent @ ident
>     
>     // Use trivia to get the actual module keyword line, which excludes attributes
>     let moduleKeywordLine = 
>         match trivia.ModuleKeyword with
>         | Some moduleKeywordRange -> moduleKeywordRange.StartLine
>         | None -> range.StartLine  // Fallback if trivia unavailable
>     
>     let startLine = moduleKeywordLine - 1
>     
>     let moduleBodyIndentation =
>         getMinColumn decls |> Option.defaultValue (range.StartColumn + 4)
> 
>     doRange NestedModule fullIdent moduleKeywordLine moduleBodyIndentation
>     List.iter (walkSynModuleDecl fullIdent) decls
> ```
> 
> **Explanation:** The issue is that `range.StartLine` includes attributes. By using `trivia.ModuleKeyword.StartLine`, we get the exact line where the `module` keyword appears, skipping all attributes regardless of how many lines they span.
> 
> ### Part 2: Simplify AddOpenCodeFixProvider (Remove Workaround)
> 
> **File:** `vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs`
> **Location:** Lines 33-88, the `getOpenDeclaration` function
> 
> **Current Code (with hack comments):**
> ```fsharp
> // Hey, I know what you're thinking: this is a horrible hack.
> // Indeed it is, this is a better (but still bad) version of the OpenDeclarationHelper.
> // The things should be actually fixed in the InsertionContext, it's bugged.
> // But currently CompletionProvider also depends on InsertionContext and it's not tested enough.
> // So fixing InsertionContext or OpenDeclarationHelper might break completion which would be bad.
> // The hack below is at least heavily tested.
> // And at least it shows what should be fixed down the line.
> let getOpenDeclaration (sourceText: SourceText) (ctx: InsertionContext) (ns: string) =
>     // insertion context counts from 2, make the world sane
>     let insertionLineNumber = ctx.Pos.Line - 2
>     let margin = String(' ', ctx.Pos.Column)
> 
>     let startLineNumber, openDeclaration =
>         match ctx.ScopeKind with
>         | ScopeKind.TopModule ->
>             match sourceText.Lines[insertionLineNumber].ToString().Trim() with
> 
>             // explicit top level module
>             | line when line.StartsWith "module" && not (line.EndsWith "=") -> insertionLineNumber + 2, $"{margin}open {ns}{br}{br}"
> 
>             // nested module, shouldn't be here
>             | line when line.StartsWith "module" -> insertionLineNumber, $"{margin}open {ns}{br}{br}"
> 
>             // attribute, shouldn't be here
>             | line when line.StartsWith "[<" && line.EndsWith ">]" ->
>                 let moduleDeclLineNumberOpt =
>                     sourceText.Lines
>                     |> Seq.skip insertionLineNumber
>                     |> Seq.tryFindIndex (fun line -> line.ToString().Contains "module")
> 
>                 match moduleDeclLineNumberOpt with
>                 // implicit top level module
>                 | None -> insertionLineNumber, $"{margin}open {ns}{br}{br}"
>                 // explicit top level module
>                 | Some number ->
>                     // add back the skipped lines
>                     let moduleDeclLineNumber = insertionLineNumber + number
>                     let moduleDeclLineText = sourceText.Lines[moduleDeclLineNumber].ToString().Trim()
> 
>                     if moduleDeclLineText.EndsWith "=" then
>                         insertionLineNumber, $"{margin}open {ns}{br}{br}"
>                     else
>                         moduleDeclLineNumber + 2, $"{margin}open {ns}{br}{br}"
> 
>             // implicit top level module
>             | _ -> insertionLineNumber, $"{margin}open {ns}{br}{br}"
> 
>         | ScopeKind.Namespace -> insertionLineNumber + 3, $"{margin}open {ns}{br}{br}"
>         | ScopeKind.NestedModule -> insertionLineNumber + 2, $"{margin}open {ns}{br}{br}"
>         | ScopeKind.OpenDeclaration -> insertionLineNumber + 1, $"{margin}open {ns}{br}"
> 
>         // So far I don't know how to get here
>         | ScopeKind.HashDirective -> insertionLineNumber + 1, $"open {ns}{br}{br}"
> 
>     let start = sourceText.Lines[startLineNumber].Start
>     TextChange(TextSpan(start, 0), openDeclaration)
> ```
> 
> **Replace With:**
> ```fsharp
> // With the fix in ServiceParsedInputOps, the InsertionContext now correctly
> // points to the line after the module keyword (or namespace), so we can trust it.
> let getOpenDeclaration (sourceText: SourceText) (ctx: InsertionContext) (ns: string) =
>     // insertion context counts from 2, make the world sane
>     let insertionLineNumber = ctx.Pos.Line - 2
>     let margin = String(' ', ctx.Pos.Column)
> 
>     let startLineNumber, openDeclaration =
>         match ctx.ScopeKind with
>         | ScopeKind.TopModule -> insertionLineNumber + 2, $"{margin}open {ns}{br}{br}"
>         | ScopeKind.Namespace -> insertionLineNumber + 3, $"{margin}open {ns}{br}{br}"
>         | ScopeKind.NestedModule -> insertionLineNumber + 2, $"{margin}open {ns}{br}{br}"
>         | ScopeKind.OpenDeclaration -> insertionLineNumber + 1, $"{margin}open {ns}{br}"
>         | ScopeKind.HashDirective -> insertionLineNumber + 1, $"open {ns}{br}{br}"
> 
>     let start = sourceText.Lines[startLineNumber].Start
>     TextChange(TextSpan(start, 0), openDeclaration)
> ```
> 
> **Explanation:** With the compiler service fixed, we no longer need string-based heuristics to detect attributes or scan for "module" keywords. The insertion context is now correct.
> 
> ### Part 3: Add Tests
> 
> **File:** `vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOffTests.fs`
> **Location:** Add after line 434 (after the last test)
> 
> ```fsharp
> [<Fact>]
> let ``Fixes FS0039 for missing opens - module has multiline attributes`` () =
>     let code =
>         """
> namespace X
> 
> open System
> 
> [<RequireQualifiedAccess;
>   CompiledName((nameof System.Collections.Immutable.ImmutableArray)
>                + "Module")>]
> module FlatList =
> 
>     let a : KeyValuePair<string, int> = KeyValuePair<string, int>("key", 1)
> """
> 
>     let expected =
>         Some
>             {
>                 Message = "open System.Collections.Generic"
>                 FixedCode =
>                     """
> namespace X
> 
> open System
> 
> [<RequireQualifiedAccess;
>   CompiledName((nameof System.Collections.Immutable.ImmutableArray)
>                + "Module")>]
> module FlatList =
> 
>     open System.Collections.Generic
> 
>     let a : KeyValuePair<string, int> = KeyValuePair<string, int>("key", 1)
> """
>             }
> 
>     let actual = codeFix |> tryFix code mode
> 
>     Assert.Equal(expected, actual)
> ```
> 
> **File:** `vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOnTests.fs`
> **Location:** Add after line 427 (after the last test)
> 
> Add the same test as above - this tests the "AlwaysPlaceOpensAtTopLevel = true" mode.
> 
> ## Testing Plan
> 
> 1. **Run all existing AddOpen tests** - Should all pass (no regressions)
>    ```bash
>    dotnet test vsintegration/tests/FSharp.Editor.Tests --filter "AddOpen"
>    ```
> 
> 2. **New tests pass** - The multiline attribute tests should pass
> 
> 3. **Manual verification** - Test in Visual Studio with the exact code from issue #18671
> 
> ## Impact Assessment
> 
> **Benefits:**
> - Fixes issue #18671
> - Also fixes auto-import on completion for multiline attributes
> - Removes fragile string-based workaround code
> - Cleaner, more maintainable codebase
> 
> **Risk Level:** Low-Medium
> - Low risk in compiler service (uses proper trivia, has fallback)
> - Medium risk in code fix provider (removes workaround, but heavily tested)
> - All changes covered by 40+ existing tests plus new ones
> 
> Fixes #18671

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI and others added 2 commits November 10, 2025 17:06
…ttributes

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix incorrect open statement placement for modules Fix incorrect open statement placement for modules with multiline attributes Nov 10, 2025
Copilot AI requested a review from T-Gro November 10, 2025 17:28
Copilot finished work on behalf of T-Gro November 10, 2025 17:29
@T-Gro
Copy link
Member

T-Gro commented Nov 11, 2025

@copilot :
Test failures indicate you have off by 1/2 errors.
Two areas of problems.

////////1. Plain crashing

Failed FSharp.Editor.Tests.CodeFixes.AddOpenOnTopOnTests.Fixes FS0039 for missing opens - multiple first lines are empty [583 ms]
Error Message:
System.ArgumentOutOfRangeException : Specified argument was out of the range of valid values.
Parameter name: index
Stack Trace:
at Microsoft.CodeAnalysis.Text.SourceText.LineInfo.get_Item(Int32 index)
at Microsoft.VisualStudio.FSharp.Editor.AddOpenCodeFixProvider.getOpenDeclaration(SourceText sourceText, InsertionContext ctx, String ns) in D:\a_work\1\s\vsintegration\src\FSharp.Editor\CodeFixes\AddOpenCodeFixProvider.fs:line 46
at Microsoft.VisualStudio.FSharp.Editor.AddOpenCodeFixProvider.openNamespaceFix(InsertionContext ctx, String name, String ns, Boolean multipleNames, SourceText sourceText) in D:\a_work\1\s\vsintegration\src\FSharp.Editor\CodeFixes\AddOpenCodeFixProvider.fs:line 53
at <StartupCode$FSharp-Editor>.$AddOpenCodeFixProvider.clo@81-160.Invoke(Tuple`4 tupledArg) in D:\a_work\1\s\vsintegration\src\FSharp.Editor\CodeFixes\AddOpenCodeFixProvider.fs:line 81

////////2. Missed expectations:
Failed FSharp.Editor.Tests.CodeFixes.AddOpenOnTopOffTests.Fixes FS0039 for missing opens - explicit module has attributes [285 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: Some({ Message = "open System"
FixedCode =
"
[]
module Module1

      open System
      
      Console.WriteLine 42
      " })

Actual: Some({ Message = "open System"
FixedCode =
"
[]
module Module1
open System

      Console.WriteLine 42
      " })

Stack Trace:
at FSharp.Editor.Tests.CodeFixes.AddOpenOnTopOffTests.Fixes FS0039 for missing opens - explicit module has attributes()

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 11, 2025

@copilot :
Test failures indicate you have off by 1/2 errors.
Two areas of problems.
...

Fixed in d8f4a1a. The initial implementation only handled nested modules with attributes, but not top-level modules. Updated walkSynModuleOrNamespace to also use trivia.LeadingKeyword for top-level modules, and removed only the multiline attribute workaround from AddOpenCodeFixProvider.fs while keeping the implicit module handling logic.

Copilot finished work on behalf of T-Gro November 11, 2025 11:45
@T-Gro
Copy link
Member

T-Gro commented Nov 11, 2025

@copilot :

Another failure. notice bad placement of the open.

Failed FSharp.Editor.Tests.CodeFixes.AddOpenOnTopOnTests.Fixes FS0039 for missing opens - explicit namespace [266 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: Some({ Message = "open System"
FixedCode =
"
namespace N1

      open System
      
      module M1 =
      
          Console.WriteLine 42
      " })

Actual: Some({ Message = "open System"
FixedCode =
"
namespace N1

      module M1 =
      open System
      
      
          Console.WriteLine 42
      " })

Stack Trace:
at FSharp.Editor.Tests.CodeFixes.AddOpenOnTopOnTests.Fixes FS0039 for missing opens - explicit namespace()

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 11, 2025

@copilot :

Another failure. notice bad placement of the open.
...

Fixed in cd2861c. The namespace case requires using namespaceRange.StartLine - 1 instead of just namespaceRange.StartLine to preserve the original behavior and work correctly with the insertionLineNumber + 3 offset in AddOpenCodeFixProvider.

Copilot finished work on behalf of T-Gro November 11, 2025 13:00
@github-actions
Copy link
Contributor

github-actions bot commented Nov 11, 2025

❗ Release notes required


✅ Found changes and release notes in following paths:

Warning

No PR link found in some release notes, please consider adding it.

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/11.0.0.md No current pull request URL (#19066) found, please consider adding it
vsintegration/src docs/release-notes/.VisualStudio/18.0.md No current pull request URL (#19066) found, please consider adding it

@github-actions
Copy link
Contributor

❗ Release notes required

@copilot,

Caution

No release notes found for the changed paths (see table below).

Please make sure to add an entry with an informative description of the change as well as link to this pull request, issue and language suggestion if applicable. Release notes for this repository are based on Keep A Changelog format.

The following format is recommended for this repository:

* <Informative description>. ([PR #XXXXX](https://github.com/dotnet/fsharp/pull/XXXXX))

See examples in the files, listed in the table below or in th full documentation at https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html.

If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

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

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/11.0.0.md No release notes found or release notes format is not correct
vsintegration/src docs/release-notes/.VisualStudio/18.0.md No release notes found or release notes format is not correct

@T-Gro
Copy link
Member

T-Gro commented Nov 11, 2025

@copilot You forgot to add release notes.
Change path Release notes path Description
src/Compiler
docs/release-notes/.FSharp.Compiler.Service/11.0.0.md No release notes found or release notes format is not correct

vsintegration/src
docs/release-notes/.VisualStudio/18.0.md No release notes found or release notes format is not correct

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 11, 2025

@copilot You forgot to add release notes.
Change path Release notes path Description
src/Compiler ...

Added in d753b72. Release notes added to:

  • docs/release-notes/.FSharp.Compiler.Service/11.0.0.md
  • docs/release-notes/.VisualStudio/18.0.md

Copilot finished work on behalf of T-Gro November 11, 2025 13:33
@T-Gro T-Gro marked this pull request as ready for review November 11, 2025 13:57
@T-Gro T-Gro requested a review from a team as a code owner November 11, 2025 13:57
@T-Gro
Copy link
Member

T-Gro commented Nov 11, 2025

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@T-Gro
Copy link
Member

T-Gro commented Nov 11, 2025

@copilot

❌ Build / Test Failures

💥 Issues

  • Cmd.exe exited with code '1'. — WindowsCompressedMetadata vs_release/Build and Test testVs
  • (NETCORE_ENGINEERING_TELEMETRY=Test) Failure running tests — WindowsCompressedMetadata vs_release/Build and Test testVs
  • .packages\microsoft.dotnet.arcade.sdk\11.0.0-beta.25560.1\tools\Publish.proj(428,5): error : (NETCORE_ENGINEERING_TELEMETRY=Publish) ItemsToPush is not specified. — Benchmarks/Smoke test fast benchmarks

🏗️ Jobs

  • Benchmarks/Smoke test fast benchmarks: .packages\microsoft.dotnet.arcade.sdk\11.0.0-beta.25560.1\tools\Publish.proj(428,5): error : (NETCORE_ENGINEERING_TELEMETRY=Publish) ItemsToPush is not specifie...
  • Build/WindowsCompressedMetadata
  • WindowsCompressedMetadata vs_release/Build and Test testVs: (NETCORE_ENGINEERING_TELEMETRY=Test) Failure running tests
  • WindowsCompressedMetadata/WindowsCompressedMetadata vs_release

🧪 Tests (1)

  • FSharp.Editor.Tests.CodeFixes.AddOpenOnTopOnTests.Fixes FS0039 for missing opens - module has multiline attributes: Assert.Equal() Failure: Values differ ⏎ Expected: Some({ Message = "open System.Collections.Generic" ⏎ FixedCode = ⏎ " ⏎ namespace X ⏎ open System ⏎ [<RequireQualifiedAccess; ⏎ CompiledName((nameof System.Collections.Immutable.ImmutableArray) ⏎ + "Module")>] ⏎ module FlatList = ⏎ open System.Collections.Generic ⏎ let a : KeyValuePair<string, int> = KeyValuePair<string, int>("key", 1) ⏎ " }) ⏎ Actual: Some({ Message = "open System.Collections.Generic" ⏎ FixedCode = ⏎ at FS...
    Full build

…TopLevel

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 11, 2025

@copilot

❌ Build / Test Failures...

Fixed test expectation in f2d08ad. The test in AddOpenOnTopOnTests.fs was expecting the open inside the module, but with AlwaysPlaceOpensAtTopLevel = true, it should be placed at the namespace level (grouping with the existing open System). Updated the expected output to place open System.Collections.Generic at the namespace level.

Copilot finished work on behalf of T-Gro November 11, 2025 15:09
@T-Gro
Copy link
Member

T-Gro commented Nov 11, 2025

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@github-project-automation github-project-automation bot moved this from New to In Progress in F# Compiler and Tooling Nov 11, 2025
@T-Gro T-Gro enabled auto-merge (squash) November 11, 2025 16:02
@T-Gro T-Gro merged commit fd28b12 into main Nov 11, 2025
40 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in F# Compiler and Tooling Nov 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Opening namespace in module with multiline attributes puts the open into a wrong position (within attributes)

3 participants