Skip to content

Commit caab632

Browse files
committed
Introduce ConditionalDirectiveTrivia.
1 parent 517e054 commit caab632

16 files changed

+226
-24
lines changed

src/fsharp/CheckDeclarations.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5959,7 +5959,7 @@ let TypeCheckOneImplFile
59595959
rootSigOpt: ModuleOrNamespaceType option,
59605960
synImplFile) =
59615961

5962-
let (ParsedImplFileInput (_, isScript, qualNameOfFile, scopedPragmas, _, implFileFrags, isLastCompiland)) = synImplFile
5962+
let (ParsedImplFileInput (_, isScript, qualNameOfFile, scopedPragmas, _, implFileFrags, isLastCompiland, _)) = synImplFile
59635963
let infoReader = InfoReader(g, amap)
59645964

59655965
cancellable {

src/fsharp/ParseAndCheckInputs.fs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ let PrependPathToSpec x (SynModuleOrNamespaceSig(p, b, c, d, e, f, g, h)) =
8080

8181
let PrependPathToInput x inp =
8282
match inp with
83-
| ParsedInput.ImplFile (ParsedImplFileInput (b, c, q, d, hd, impls, e)) ->
84-
ParsedInput.ImplFile (ParsedImplFileInput (b, c, PrependPathToQualFileName x q, d, hd, List.map (PrependPathToImpl x) impls, e))
83+
| ParsedInput.ImplFile (ParsedImplFileInput (b, c, q, d, hd, impls, e, trivia)) ->
84+
ParsedInput.ImplFile (ParsedImplFileInput (b, c, PrependPathToQualFileName x q, d, hd, List.map (PrependPathToImpl x) impls, e, trivia))
8585

8686
| ParsedInput.SigFile (ParsedSigFileInput (b, q, d, hd, specs)) ->
8787
ParsedInput.SigFile (ParsedSigFileInput (b, PrependPathToQualFileName x q, d, hd, List.map (PrependPathToSpec x) specs))
@@ -178,7 +178,7 @@ let GetScopedPragmasForHashDirective hd =
178178
| Some n -> yield ScopedPragma.WarningOff(m, n)
179179
| _ -> () ]
180180

181-
let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImplFile (hashDirectives, impls)) =
181+
let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImplFile (hashDirectives, impls), lexbuf: UnicodeLexing.Lexbuf) =
182182
match impls |> List.rev |> List.tryPick (function ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(lid, _, _, _, _, _, _, _)) -> Some lid | _ -> None) with
183183
| Some lid when impls.Length > 1 ->
184184
errorR(Error(FSComp.SR.buildMultipleToplevelModules(), rangeOfLid lid))
@@ -197,7 +197,9 @@ let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImp
197197
for hd in hashDirectives do
198198
yield! GetScopedPragmasForHashDirective hd ]
199199

200-
ParsedInput.ImplFile (ParsedImplFileInput (filename, isScript, qualName, scopedPragmas, hashDirectives, impls, isLastCompiland))
200+
let conditionalDirectives = LexbufIfdefStore.GetTrivia(lexbuf)
201+
202+
ParsedInput.ImplFile (ParsedImplFileInput (filename, isScript, qualName, scopedPragmas, hashDirectives, impls, isLastCompiland, { ConditionalDirectives = conditionalDirectives }))
201203

202204
let PostParseModuleSpecs (defaultNamespace, filename, isLastCompiland, ParsedSigFile (hashDirectives, specs)) =
203205
match specs |> List.rev |> List.tryPick (function ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(lid, _, _, _, _, _, _, _)) -> Some lid | _ -> None) with
@@ -242,9 +244,9 @@ let DeduplicateModuleName (moduleNamesDict: ModuleNamesDict) fileName (qualNameO
242244
/// Checks if a ParsedInput is using a module name that was already given and deduplicates the name if needed.
243245
let DeduplicateParsedInputModuleName (moduleNamesDict: ModuleNamesDict) input =
244246
match input with
245-
| ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFile, scopedPragmas, hashDirectives, modules, (isLastCompiland, isExe))) ->
247+
| ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFile, scopedPragmas, hashDirectives, modules, (isLastCompiland, isExe), trivia)) ->
246248
let qualNameOfFileT, moduleNamesDictT = DeduplicateModuleName moduleNamesDict fileName qualNameOfFile
247-
let inputT = ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFileT, scopedPragmas, hashDirectives, modules, (isLastCompiland, isExe)))
249+
let inputT = ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFileT, scopedPragmas, hashDirectives, modules, (isLastCompiland, isExe), trivia))
248250
inputT, moduleNamesDictT
249251
| ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput (fileName, qualNameOfFile, scopedPragmas, hashDirectives, modules)) ->
250252
let qualNameOfFileT, moduleNamesDictT = DeduplicateModuleName moduleNamesDict fileName qualNameOfFile
@@ -279,7 +281,7 @@ let ParseInput (lexer, diagnosticOptions:FSharpDiagnosticOptions, errorLogger: E
279281
if FSharpImplFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
280282
let impl = Parser.implementationFile lexer lexbuf
281283
LexbufLocalXmlDocStore.ReportInvalidXmlDocPositions(lexbuf)
282-
PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, impl)
284+
PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, impl, lexbuf)
283285
elif FSharpSigFileSuffixes |> List.exists (FileSystemUtils.checkSuffix lower) then
284286
let intfs = Parser.signatureFile lexer lexbuf
285287
LexbufLocalXmlDocStore.ReportInvalidXmlDocPositions(lexbuf)
@@ -355,7 +357,8 @@ let EmptyParsedInput(filename, isLastCompiland) =
355357
[],
356358
[],
357359
[],
358-
isLastCompiland
360+
isLastCompiland,
361+
{ ConditionalDirectives = [] }
359362
)
360363
)
361364

@@ -649,7 +652,7 @@ let ProcessMetaCommandsFromInput
649652
let state = List.fold ProcessMetaCommand state0 hashDirectives
650653
let state = List.fold ProcessMetaCommandsFromModuleSpec state specs
651654
state
652-
| ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, hashDirectives, impls, _)) ->
655+
| ParsedInput.ImplFile (ParsedImplFileInput (hashDirectives = hashDirectives; modules = impls)) ->
653656
let state = List.fold ProcessMetaCommand state0 hashDirectives
654657
let state = List.fold ProcessMetaCommandsFromModuleImpl state impls
655658
state
@@ -871,7 +874,7 @@ let TypeCheckOneInput(checkForErrors,
871874

872875
return (tcEnv, EmptyTopAttrs, None, ccuSigForFile), tcState
873876

874-
| ParsedInput.ImplFile (ParsedImplFileInput (_, _, qualNameOfFile, _, _, _, _) as file) ->
877+
| ParsedInput.ImplFile (ParsedImplFileInput (qualifiedNameOfFile = qualNameOfFile) as file) ->
875878

876879
// Check if we've got an interface for this fragment
877880
let rootSigOpt = tcState.tcsRootSigs.TryFind qualNameOfFile

src/fsharp/ParseHelpers.fs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ open FSharp.Compiler.AbstractIL
66
open FSharp.Compiler.ErrorLogger
77
open FSharp.Compiler.Features
88
open FSharp.Compiler.Syntax
9+
open FSharp.Compiler.SyntaxTrivia
910
open FSharp.Compiler.SyntaxTreeOps
1011
open FSharp.Compiler.UnicodeLexing
1112
open FSharp.Compiler.Text
@@ -87,7 +88,6 @@ type IParseState with
8788
//------------------------------------------------------------------------
8889

8990
/// XmlDoc F# lexer/parser state, held in the BufferLocalStore for the lexer.
90-
/// This is the only use of the lexer BufferLocalStore in the codebase.
9191
module LexbufLocalXmlDocStore =
9292
// The key into the BufferLocalStore used to hold the current accumulated XmlDoc lines
9393
let private xmlDocKey = "XmlDoc"
@@ -177,6 +177,48 @@ let rec LexerIfdefEval (lookup: string -> bool) = function
177177
| IfdefNot e -> not (LexerIfdefEval lookup e)
178178
| IfdefId id -> lookup id
179179

180+
/// Ifdef F# lexer/parser state, held in the BufferLocalStore for the lexer.
181+
/// Used to capture #if, #else and #endif as syntax trivia.
182+
module LexbufIfdefStore =
183+
// The key into the BufferLocalStore used to hold the compiler directives
184+
let private ifDefKey = "Ifdef"
185+
186+
let private getStore (lexbuf: Lexbuf): ResizeArray<ConditionalDirectiveTrivia> =
187+
match lexbuf.BufferLocalStore.TryGetValue ifDefKey with
188+
| true, store -> store
189+
| _ ->
190+
let store = box (ResizeArray<ConditionalDirectiveTrivia>())
191+
lexbuf.BufferLocalStore.[ifDefKey] <- store
192+
store
193+
|> unbox<ResizeArray<ConditionalDirectiveTrivia>>
194+
195+
let SaveIfHash (lexbuf: Lexbuf, expr: LexerIfdefExpression, range: range) =
196+
let store = getStore lexbuf
197+
198+
let expr =
199+
let rec visit (expr: LexerIfdefExpression) : IfDirectiveExpression =
200+
match expr with
201+
| LexerIfdefExpression.IfdefAnd(l,r) -> IfDirectiveExpression.IfdefAnd(visit l, visit r)
202+
| LexerIfdefExpression.IfdefOr(l, r) -> IfDirectiveExpression.IfdefOr(visit l, visit r)
203+
| LexerIfdefExpression.IfdefNot e -> IfDirectiveExpression.IfdefNot(visit e)
204+
| LexerIfdefExpression.IfdefId id -> IfDirectiveExpression.IfdefId id
205+
206+
visit expr
207+
208+
store.Add(ConditionalDirectiveTrivia.IfDirectiveTrivia(expr, range))
209+
210+
let SaveElseHash (lexbuf: Lexbuf, range: range) =
211+
let store = getStore lexbuf
212+
store.Add(ConditionalDirectiveTrivia.ElseDirectiveTrivia(range))
213+
214+
let SaveEndIfHash (lexbuf: Lexbuf, range: range) =
215+
let store = getStore lexbuf
216+
store.Add(ConditionalDirectiveTrivia.EndIfDirectiveTrivia(range))
217+
218+
let GetTrivia (lexbuf: Lexbuf): ConditionalDirectiveTrivia list =
219+
let store = getStore lexbuf
220+
Seq.toList store
221+
180222
//------------------------------------------------------------------------
181223
// Parsing: continuations for whitespace tokens
182224
//------------------------------------------------------------------------

src/fsharp/ParseHelpers.fsi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ type LexerIfdefExpression =
7474

7575
val LexerIfdefEval: lookup:(string -> bool) -> _arg1:LexerIfdefExpression -> bool
7676

77+
module LexbufIfdefStore =
78+
79+
val SaveIfHash: lexbuf:UnicodeLexing.Lexbuf * expr: LexerIfdefExpression * range: range -> unit
80+
81+
val SaveElseHash: lexbuf:UnicodeLexing.Lexbuf * range: range -> unit
82+
83+
val SaveEndIfHash: lexbuf:UnicodeLexing.Lexbuf * range: range -> unit
84+
85+
val GetTrivia: lexbuf:UnicodeLexing.Lexbuf -> SyntaxTrivia.ConditionalDirectiveTrivia list
86+
7787
[<RequireQualifiedAccess>]
7888
type LexerStringStyle =
7989
| Verbatim

src/fsharp/ScriptClosure.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,13 @@ module ScriptPreprocessClosure =
355355
match List.frontAndBack closureFiles with
356356
| rest, ClosureFile
357357
(filename, m,
358-
Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, _))),
358+
Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, _, trivia))),
359359
parseDiagnostics, metaDiagnostics, nowarns) ->
360360

361361
let isLastCompiland = (true, tcConfig.target.IsExe)
362362
rest @ [ClosureFile
363363
(filename, m,
364-
Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, isLastCompiland))),
364+
Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, isLastCompiland, trivia))),
365365
parseDiagnostics, metaDiagnostics, nowarns)]
366366

367367
| _ -> closureFiles

src/fsharp/SyntaxTree.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2014,7 +2014,8 @@ type ParsedImplFileInput =
20142014
scopedPragmas: ScopedPragma list *
20152015
hashDirectives: ParsedHashDirective list *
20162016
modules: SynModuleOrNamespace list *
2017-
isLastCompiland: (bool * bool)
2017+
isLastCompiland: (bool * bool) *
2018+
trivia: ParsedImplFileInputTrivia
20182019

20192020
[<NoEquality; NoComparison>]
20202021
type ParsedSigFileInput =

src/fsharp/SyntaxTree.fsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2207,7 +2207,8 @@ type ParsedImplFileInput =
22072207
scopedPragmas: ScopedPragma list *
22082208
hashDirectives: ParsedHashDirective list *
22092209
modules: SynModuleOrNamespace list *
2210-
isLastCompiland: (bool * bool)
2210+
isLastCompiland: (bool * bool) *
2211+
trivia: ParsedImplFileInputTrivia
22112212

22122213
/// Represents the full syntax tree, file name and other parsing information for a signature file
22132214
[<NoEquality; NoComparison>]

src/fsharp/SyntaxTrivia.fs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ namespace FSharp.Compiler.SyntaxTrivia
44

55
open FSharp.Compiler.Text
66

7+
[<RequireQualifiedAccess; NoEquality; NoComparison>]
8+
type ConditionalDirectiveTrivia =
9+
| IfDirectiveTrivia of expr:IfDirectiveExpression * range:range
10+
| ElseDirectiveTrivia of range:range
11+
| EndIfDirectiveTrivia of range:range
12+
13+
and IfDirectiveExpression =
14+
| IfdefAnd of IfDirectiveExpression * IfDirectiveExpression
15+
| IfdefOr of IfDirectiveExpression * IfDirectiveExpression
16+
| IfdefNot of IfDirectiveExpression
17+
| IfdefId of string
18+
19+
[<NoEquality; NoComparison>]
20+
type ParsedImplFileInputTrivia =
21+
{ ConditionalDirectives: ConditionalDirectiveTrivia list }
22+
723
[<NoEquality; NoComparison>]
824
type SynExprTryWithTrivia =
925
{ TryKeyword: range

src/fsharp/SyntaxTrivia.fsi

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@ namespace FSharp.Compiler.SyntaxTrivia
44

55
open FSharp.Compiler.Text
66

7+
[<RequireQualifiedAccess; NoEquality; NoComparison>]
8+
type ConditionalDirectiveTrivia =
9+
| IfDirectiveTrivia of expr:IfDirectiveExpression * range:range
10+
| ElseDirectiveTrivia of range:range
11+
| EndIfDirectiveTrivia of range:range
12+
13+
and IfDirectiveExpression =
14+
| IfdefAnd of IfDirectiveExpression * IfDirectiveExpression
15+
| IfdefOr of IfDirectiveExpression * IfDirectiveExpression
16+
| IfdefNot of IfDirectiveExpression
17+
| IfdefId of string
18+
19+
/// Represents additional information for ParsedImplFileInput
20+
[<NoEquality; NoComparison>]
21+
type ParsedImplFileInputTrivia =
22+
{
23+
/// Preprocessor directives of type #if, #else or #endif
24+
ConditionalDirectives: ConditionalDirectiveTrivia list
25+
}
26+
727
/// Represents additional information for SynExpr.TryWith
828
[<NoEquality; NoComparison>]
929
type SynExprTryWithTrivia =
@@ -178,4 +198,4 @@ type SynModuleSigDeclNestedModuleTrivia =
178198
/// The syntax range of the `=` token.
179199
EqualsRange: range option
180200
}
181-
static member Zero: SynModuleSigDeclNestedModuleTrivia
201+
static member Zero: SynModuleSigDeclNestedModuleTrivia

src/fsharp/fsi/fsi.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1778,7 +1778,7 @@ type internal FsiDynamicCompiler
17781778
let impl = SynModuleOrNamespace(prefix,(*isRec*)false, SynModuleOrNamespaceKind.NamedModule,defs,PreXmlDoc.Empty,[],None,m)
17791779
let isLastCompiland = true
17801780
let isExe = false
1781-
let input = ParsedInput.ImplFile (ParsedImplFileInput (filename,true, ComputeQualifiedNameOfFileFromUniquePath (m,prefixPath),[],[],[impl],(isLastCompiland, isExe) ))
1781+
let input = ParsedInput.ImplFile (ParsedImplFileInput (filename,true, ComputeQualifiedNameOfFileFromUniquePath (m,prefixPath),[],[],[impl],(isLastCompiland, isExe), { ConditionalDirectives = [] }))
17821782
let isIncrementalFragment = true
17831783
let istate,tcEnvAtEndOfLastInput,declaredImpls = ProcessInputs (ctok, errorLogger, istate, [input], showTypes, isIncrementalFragment, isInteractiveItExpr, prefix, m)
17841784
let tcState = istate.tcState

0 commit comments

Comments
 (0)