diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index ce5571ab4d9..9127727c196 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -47,10 +47,14 @@ type SynLongIdent =
member this.IdentsWithTrivia =
let (SynLongIdent (lid, _, trivia)) = this
- if lid.Length <> trivia.Length then
- failwith "difference between idents and trivia"
- else
+ if lid.Length = trivia.Length then
+ List.zip lid trivia |> List.map SynIdent
+ elif lid.Length > trivia.Length then
+ let delta = lid.Length - trivia.Length
+ let trivia = [ yield! trivia; yield! List.replicate delta None ]
List.zip lid trivia |> List.map SynIdent
+ else
+ failwith "difference between idents and trivia"
member this.ThereIsAnExtraDotAtTheEnd =
match this with
diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs
index b36ec372a78..ef3673fa44f 100644
--- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs
@@ -468,7 +468,7 @@ let mkSynDotMissing mDot m l =
| SynExpr.LongIdent (isOpt, SynLongIdent (lid, dots, trivia), None, _) ->
// REVIEW: MEMORY PERFORMANCE: This list operation is memory intensive (we create a lot of these list nodes)
SynExpr.LongIdent(isOpt, SynLongIdent(lid, dots @ [ mDot ], trivia), None, m)
- | SynExpr.Ident id -> SynExpr.LongIdent(false, SynLongIdent([ id ], [ mDot ], []), None, m)
+ | SynExpr.Ident id -> SynExpr.LongIdent(false, SynLongIdent([ id ], [ mDot ], [ None ]), None, m)
| SynExpr.DotGet (e, dm, SynLongIdent (lid, dots, trivia), _) -> SynExpr.DotGet(e, dm, SynLongIdent(lid, dots @ [ mDot ], trivia), m) // REVIEW: MEMORY PERFORMANCE: This is memory intensive (we create a lot of these list nodes)
| expr -> SynExpr.DiscardAfterMissingQualificationAfterDot(expr, m)
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
index fae9537443b..19175fd7f05 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
@@ -113,6 +113,9 @@
SyntaxTree\OperatorNameTests.fs
+
+ SyntaxTree\SynIdentTests.fs
+
FileSystemTests.fs
diff --git a/tests/service/SyntaxTreeTests/SynIdentTests.fs b/tests/service/SyntaxTreeTests/SynIdentTests.fs
new file mode 100644
index 00000000000..887910e1448
--- /dev/null
+++ b/tests/service/SyntaxTreeTests/SynIdentTests.fs
@@ -0,0 +1,31 @@
+module FSharp.Compiler.Service.Tests.SyntaxTreeTests.SynIdentTests
+
+open FSharp.Compiler.Service.Tests.Common
+open FSharp.Compiler.Syntax
+open FSharp.Compiler.Text
+open NUnit.Framework
+
+[]
+let ``Incomplete long ident`` () =
+ let ast =
+ """
+module Module
+
+A.
+"""
+ |> getParseResults
+
+ match ast with
+ | ParsedInput.ImplFile (ParsedImplFileInput(modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls =
+ [ SynModuleDecl.Expr(expr = SynExpr.LongIdent (longDotId = lid)) ]) ])) ->
+ Assert.AreEqual(1, lid.IdentsWithTrivia.Length)
+ | _ -> Assert.Fail $"Could not get valid AST, got {ast}"
+
+[]
+let ``IdentsWithTrivia with unbalance collection should not throw`` () =
+ let synLongIdent =
+ SynLongIdent([ Ident("A", Range.Zero); Ident("B", Range.Zero) ], [ Range.Zero ], [ None ])
+
+ match synLongIdent.IdentsWithTrivia with
+ | [ SynIdent (_, None); SynIdent (_, None) ] -> Assert.Pass()
+ | identsWithTrivia -> Assert.Fail $"Unexpected identsWithTrivia, got {identsWithTrivia}"