Skip to content

Commit

Permalink
Parser: recover on unfinished namespaces and top level modules
Browse files Browse the repository at this point in the history
  • Loading branch information
auduchinok committed Jun 19, 2023
1 parent fd05137 commit d6c6d3c
Show file tree
Hide file tree
Showing 29 changed files with 255 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -527,13 +527,22 @@ moduleIntro:
let mModule = rhs parseState 1
mModule, $4, [], $3, $2 }

| moduleKeyword opt_attributes opt_access opt_rec recover
{ if not (isNil $2) then
parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AttributesToRightOfModuleKeyword (rhs parseState 4)
let mModule = rhs parseState 1
mModule, $4, [], $3, $2 }

/* The start of a namespace declaration */
namespaceIntro:
| NAMESPACE opt_rec path
{ let mNamespace = rhs parseState 1
mNamespace, $2, $3.LongIdent, grabXmlDoc(parseState, [], 1) }

| NAMESPACE opt_rec recover
{ let mNamespace = rhs parseState 1
mNamespace, $2, [], grabXmlDoc(parseState, [], 1) }


/* The contents of a signature file */
fileNamespaceSpecs:
Expand Down Expand Up @@ -1138,8 +1147,8 @@ fileModuleImpl:
| moduleDefnsOrExprPossiblyEmptyOrBlock
{ let m = (rhs parseState 1)
(fun (mNamespaceOpt, isRec, path, xml) ->
match path with
| [] -> ParsedImplFileFragment.AnonModule($1, m)
match path, mNamespaceOpt with
| [], None -> ParsedImplFileFragment.AnonModule($1, m)
| _ ->
let lastDeclRange = List.tryLast $1 |> Option.map (fun decl -> decl.Range) |> Option.defaultValue (rhs parseState 1)
let m = mkRange lastDeclRange.FileName (lhs parseState).Start lastDeclRange.End
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
()
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Anon module 01.fs", false,
QualifiedNameOfFile Anon module 01, [], [],
[SynModuleOrNamespace
([Anon module 01], false, AnonModule,
[Expr (Const (Unit, (1,0--1,2)), (1,0--1,2))], PreXmlDocEmpty, [],
None, (1,0--1,2), { LeadingKeyword = None })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(1,0)-(1,2) parse warning The declarations in this file will be placed in an implicit module 'Anon module 01' based on the file name 'Anon module 01.fs'. However this is not a valid F# identifier, so the contents will not be accessible from other files. Consider renaming the file or adding a 'module' or 'namespace' declaration at the top of the file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
()
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Anon module 02.fsx", true,
QualifiedNameOfFile Anon module 02$fsx, [], [],
[SynModuleOrNamespace
([Anon module 02], false, AnonModule,
[Expr (Const (Unit, (1,0--1,2)), (1,0--1,2))], PreXmlDocEmpty, [],
None, (1,0--1,2), { LeadingKeyword = None })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))
3 changes: 3 additions & 0 deletions tests/service/data/SyntaxTree/ModuleOrNamespace/Module 05.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A.

()
12 changes: 12 additions & 0 deletions tests/service/data/SyntaxTree/ModuleOrNamespace/Module 05.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Module 05.fs", false, QualifiedNameOfFile A, [],
[],
[SynModuleOrNamespace
([A], false, NamedModule, [Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(3,0)-(3,1) parse error Unexpected start of structured construct in definition
3 changes: 3 additions & 0 deletions tests/service/data/SyntaxTree/ModuleOrNamespace/Module 06.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module

()
12 changes: 12 additions & 0 deletions tests/service/data/SyntaxTree/ModuleOrNamespace/Module 06.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Module 06.fs", false, QualifiedNameOfFile , [],
[],
[SynModuleOrNamespace
([], false, NamedModule, [Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(3,0)-(3,1) parse error Unexpected start of structured construct in definition. Expected identifier, 'global' or other token.
3 changes: 3 additions & 0 deletions tests/service/data/SyntaxTree/ModuleOrNamespace/Module 07.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module rec

()
12 changes: 12 additions & 0 deletions tests/service/data/SyntaxTree/ModuleOrNamespace/Module 07.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Module 07.fs", false, QualifiedNameOfFile , [],
[],
[SynModuleOrNamespace
([], true, NamedModule, [Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(3,0)-(3,1) parse error Unexpected start of structured construct in definition. Expected identifier, 'global' or other token.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ns1

()

namespace Ns2.Nested

()
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 01.fs", false,
QualifiedNameOfFile Namespace 01, [], [],
[SynModuleOrNamespace
([Ns1], false, DeclaredNamespace,
[Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [],
None, (1,0--3,2), { LeadingKeyword = Namespace (1,0--1,9) });
SynModuleOrNamespace
([Ns2; Nested], false, DeclaredNamespace,
[Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], PreXmlDocEmpty, [],
None, (5,0--7,2), { LeadingKeyword = Namespace (5,0--5,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ns1

()

namespace

()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 02.fs", false,
QualifiedNameOfFile Namespace 02, [], [],
[SynModuleOrNamespace
([Ns1], false, DeclaredNamespace,
[Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [],
None, (1,0--3,2), { LeadingKeyword = Namespace (1,0--1,9) });
SynModuleOrNamespace
([], false, DeclaredNamespace,
[Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], PreXmlDocEmpty, [],
None, (5,0--7,2), { LeadingKeyword = Namespace (5,0--5,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))

(7,0)-(7,1) parse error Unexpected start of structured construct in implementation file. Expected identifier, 'global' or other token.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ns1

()

namespace Ns2.

()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 03.fs", false,
QualifiedNameOfFile Namespace 03, [], [],
[SynModuleOrNamespace
([Ns1], false, DeclaredNamespace,
[Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [],
None, (1,0--3,2), { LeadingKeyword = Namespace (1,0--1,9) });
SynModuleOrNamespace
([Ns2], false, DeclaredNamespace,
[Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], PreXmlDocEmpty, [],
None, (5,0--7,2), { LeadingKeyword = Namespace (5,0--5,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))

(7,0)-(7,1) parse error Unexpected start of structured construct in implementation file
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ns1

()

namespace rec

()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 04.fs", false,
QualifiedNameOfFile Namespace 04, [], [],
[SynModuleOrNamespace
([Ns1], false, DeclaredNamespace,
[Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [],
None, (1,0--3,2), { LeadingKeyword = Namespace (1,0--1,9) });
SynModuleOrNamespace
([], true, DeclaredNamespace,
[Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], PreXmlDocEmpty, [],
None, (5,0--7,2), { LeadingKeyword = Namespace (5,0--5,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))

(7,0)-(7,1) parse error Unexpected start of structured construct in implementation file. Expected identifier, 'global' or other token.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
namespace
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 05.fs", false,
QualifiedNameOfFile Namespace 05, [], [],
[SynModuleOrNamespace
([], false, DeclaredNamespace, [], PreXmlDocEmpty, [], None, (1,0--2,0),
{ LeadingKeyword = Namespace (1,0--1,9) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace

()
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 06.fs", false,
QualifiedNameOfFile Namespace 06, [], [],
[SynModuleOrNamespace
([], false, DeclaredNamespace,
[Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [],
None, (1,0--3,2), { LeadingKeyword = Namespace (1,0--1,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))

(3,0)-(3,1) parse error Unexpected start of structured construct in implementation file. Expected identifier, 'global' or other token.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace

type T = int
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 07.fs", false,
QualifiedNameOfFile Namespace 07, [], [],
[SynModuleOrNamespace
([], false, DeclaredNamespace,
[Types
([SynTypeDefn
(SynComponentInfo
([], None, [], [T],
PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
false, None, (3,5--3,6)),
Simple
(TypeAbbrev
(Ok, LongIdent (SynLongIdent ([int], [], [None])),
(3,9--3,12)), (3,9--3,12)), [], None, (3,5--3,12),
{ LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,7--3,8)
WithKeyword = None })], (3,0--3,12))], PreXmlDocEmpty, [],
None, (1,0--3,12), { LeadingKeyword = Namespace (1,0--1,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))

(3,0)-(3,4) parse error Unexpected start of structured construct in implementation file. Expected identifier, 'global' or other token.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
namespace rec
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 08.fs", false,
QualifiedNameOfFile Namespace 08, [], [],
[SynModuleOrNamespace
([], true, DeclaredNamespace, [], PreXmlDocEmpty, [], None, (1,0--2,0),
{ LeadingKeyword = Namespace (1,0--1,9) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace

()

namespace Ns2

()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ImplFile
(ParsedImplFileInput
("/root/ModuleOrNamespace/Namespace 09.fs", false,
QualifiedNameOfFile Namespace 09, [], [],
[SynModuleOrNamespace
([], false, DeclaredNamespace,
[Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [],
None, (1,0--3,2), { LeadingKeyword = Namespace (1,0--1,9) });
SynModuleOrNamespace
([Ns2], false, DeclaredNamespace,
[Expr (Const (Unit, (7,0--7,2)), (7,0--7,2))], PreXmlDocEmpty, [],
None, (5,0--7,2), { LeadingKeyword = Namespace (5,0--5,9) })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))

(3,0)-(3,1) parse error Unexpected start of structured construct in implementation file. Expected identifier, 'global' or other token.

0 comments on commit d6c6d3c

Please sign in to comment.