From b81cd8183bc418fc9f12130694ea2ec5861f64e7 Mon Sep 17 00:00:00 2001 From: nojaf Date: Sat, 26 Jun 2021 13:48:40 +0200 Subject: [PATCH] Define ParsedHashDirective arguments as ParsedHashDirectiveArgument instead of strings. --- src/fsharp/ParseAndCheckInputs.fs | 21 ++++--- src/fsharp/SyntaxTree.fs | 12 +++- src/fsharp/SyntaxTree.fsi | 11 +++- src/fsharp/SyntaxTreeOps.fs | 7 +++ src/fsharp/SyntaxTreeOps.fsi | 2 + src/fsharp/fsi/fsi.fs | 18 +++--- src/fsharp/pars.fsy | 11 ++-- .../SurfaceArea.netstandard.fs | 35 +++++++++++- tests/service/Symbols.fs | 57 +++++++++++++++++++ 9 files changed, 147 insertions(+), 27 deletions(-) diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index ffe1bfe4a97..351561f585d 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -170,9 +170,12 @@ let GetScopedPragmasForHashDirective hd = [ match hd with | ParsedHashDirective("nowarn", numbers, m) -> for s in numbers do - match GetWarningNumber(m, s) with - | None -> () - | Some n -> yield ScopedPragma.WarningOff(m, n) + match s with + | ParsedHashDirectiveArgument.SourceIdentifier _ -> () + | ParsedHashDirectiveArgument.String (s, _, _) -> + match GetWarningNumber(m, s) with + | None -> () + | Some n -> yield ScopedPragma.WarningOff(m, n) | _ -> () ] let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImplFile (hashDirectives, impls)) = @@ -512,7 +515,7 @@ let ProcessMetaCommandsFromInput let mutable matchedm = range0 try match hash with - | ParsedHashDirective("I", args, m) -> + | ParsedHashDirective("I", ParsedHashDirectiveArguments args, m) -> if not canHaveScriptMetaCommands then errorR(HashIncludeNotAllowedInNonScript m) match args with @@ -523,18 +526,18 @@ let ProcessMetaCommandsFromInput | _ -> errorR(Error(FSComp.SR.buildInvalidHashIDirective(), m)) state - | ParsedHashDirective("nowarn",numbers,m) -> + | ParsedHashDirective("nowarn", ParsedHashDirectiveArguments numbers,m) -> List.fold (fun state d -> nowarnF state (m,d)) state numbers - | ParsedHashDirective(("reference" | "r"), args, m) -> + | ParsedHashDirective(("reference" | "r"), ParsedHashDirectiveArguments args, m) -> matchedm<-m ProcessDependencyManagerDirective Directive.Resolution args m state - | ParsedHashDirective(("i"), args, m) -> + | ParsedHashDirective(("i"), ParsedHashDirectiveArguments args, m) -> matchedm<-m ProcessDependencyManagerDirective Directive.Include args m state - | ParsedHashDirective("load", args, m) -> + | ParsedHashDirective("load", ParsedHashDirectiveArguments args, m) -> if not canHaveScriptMetaCommands then errorR(HashDirectiveNotAllowedInNonScript m) match args with @@ -544,7 +547,7 @@ let ProcessMetaCommandsFromInput | _ -> errorR(Error(FSComp.SR.buildInvalidHashloadDirective(), m)) state - | ParsedHashDirective("time", args, m) -> + | ParsedHashDirective("time", ParsedHashDirectiveArguments args, m) -> if not canHaveScriptMetaCommands then errorR(HashDirectiveNotAllowedInNonScript m) match args with diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 92e4dcd3db7..efec365b65d 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -1826,11 +1826,21 @@ type SynModuleOrNamespaceSig = match this with | SynModuleOrNamespaceSig (range=m) -> m +[] +type ParsedHashDirectiveArgument = + | String of value: string * stringKind: SynStringKind * range: Range + | SourceIdentifier of constant: string * value: string * range: Range + + member this.Range = + match this with + | ParsedHashDirectiveArgument.String (range=m) + | ParsedHashDirectiveArgument.SourceIdentifier (range=m) -> m + [] type ParsedHashDirective = | ParsedHashDirective of ident: string * - args: string list * + args: ParsedHashDirectiveArgument list * range: range [] diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 3c2f8b99654..a04fc70da39 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -2014,12 +2014,21 @@ type SynModuleOrNamespaceSig = /// Gets the syntax range of this construct member Range: range +/// Represents a parsed hash directive argument +[] +type ParsedHashDirectiveArgument = + | String of value: string * stringKind: SynStringKind * range: Range + | SourceIdentifier of constant: string * value: string * range: Range + + /// Gets the syntax range of this construct + member Range: range + /// Represents a parsed hash directive [] type ParsedHashDirective = | ParsedHashDirective of ident: string * - args: string list * + args: ParsedHashDirectiveArgument list * range: range /// Represents the syntax tree for the contents of a parsed implementation file diff --git a/src/fsharp/SyntaxTreeOps.fs b/src/fsharp/SyntaxTreeOps.fs index cc0bfde80a2..b620983ec25 100644 --- a/src/fsharp/SyntaxTreeOps.fs +++ b/src/fsharp/SyntaxTreeOps.fs @@ -747,3 +747,10 @@ let rec synExprContainsError inpExpr = | SynInterpolatedStringPart.FillExpr (x, _) -> Some x)) walkExpr inpExpr + +let (|ParsedHashDirectiveArguments|) (input: ParsedHashDirectiveArgument list) = + List.map + (function + | ParsedHashDirectiveArgument.String (s, _, _) -> s + | ParsedHashDirectiveArgument.SourceIdentifier (_, v, _) -> v) + input \ No newline at end of file diff --git a/src/fsharp/SyntaxTreeOps.fsi b/src/fsharp/SyntaxTreeOps.fsi index 48f7812d07b..106b7a61540 100644 --- a/src/fsharp/SyntaxTreeOps.fsi +++ b/src/fsharp/SyntaxTreeOps.fsi @@ -266,3 +266,5 @@ val inferredTyparDecls: SynValTyparDecls val noInferredTypars: SynValTyparDecls val synExprContainsError: inpExpr:SynExpr -> bool + +val ( |ParsedHashDirectiveArguments| ) : ParsedHashDirectiveArgument list -> string list \ No newline at end of file diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 61a80b2d1aa..a85d82d90fb 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2223,26 +2223,26 @@ type internal FsiInteractionProcessor let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalParsedDefinitions (ctok, errorLogger, istate, true, false, defs) - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("load", sourceFiles, m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("load", ParsedHashDirectiveArguments sourceFiles, m), _) -> let istate = fsiDynamicCompiler.CommitDependencyManagerText(ctok, istate, lexResourceManager, errorLogger) fsiDynamicCompiler.EvalSourceFiles (ctok, istate, m, sourceFiles, lexResourceManager, errorLogger),Completed None - | ParsedScriptInteraction.HashDirective (ParsedHashDirective(("reference" | "r"), [path], m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective(("reference" | "r"), ParsedHashDirectiveArguments [path], m), _) -> packageManagerDirective Directive.Resolution path m - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("i", [path], m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("i", ParsedHashDirectiveArguments [path], m), _) -> packageManagerDirective Directive.Include path m - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("I", [path], m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("I", ParsedHashDirectiveArguments [path], m), _) -> tcConfigB.AddIncludePath (m, path, tcConfig.implicitIncludeDir) fsiConsoleOutput.uprintnfnn "%s" (FSIstrings.SR.fsiDidAHashI(tcConfig.MakePathAbsolute path)) istate, Completed None - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("cd", [path], m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("cd", ParsedHashDirectiveArguments [path], m), _) -> ChangeDirectory path m istate, Completed None - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("silentCd", [path], m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("silentCd", ParsedHashDirectiveArguments [path], m), _) -> ChangeDirectory path m fsiConsolePrompt.SkipNext() (* "silent" directive *) istate, Completed None @@ -2257,14 +2257,14 @@ type internal FsiInteractionProcessor fsiConsoleOutput.uprintnfnn "%s" (FSIstrings.SR.fsiTurnedTimingOn()) {istate with timing = not istate.timing}, Completed None - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("time", [("on" | "off") as v], _), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("time", ParsedHashDirectiveArguments [("on" | "off") as v], _), _) -> if v <> "on" then fsiConsoleOutput.uprintnfnn "%s" (FSIstrings.SR.fsiTurnedTimingOff()) else fsiConsoleOutput.uprintnfnn "%s" (FSIstrings.SR.fsiTurnedTimingOn()) {istate with timing = (v = "on")}, Completed None - | ParsedScriptInteraction.HashDirective (ParsedHashDirective("nowarn", numbers, m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective("nowarn", ParsedHashDirectiveArguments numbers, m), _) -> List.iter (fun (d:string) -> tcConfigB.TurnWarningOff(m, d)) numbers istate, Completed None @@ -2293,7 +2293,7 @@ type internal FsiInteractionProcessor fsiOptions.ShowHelp(m) istate, Completed None - | ParsedScriptInteraction.HashDirective (ParsedHashDirective(c, arg, m), _) -> + | ParsedScriptInteraction.HashDirective (ParsedHashDirective(c, ParsedHashDirectiveArguments arg, m), _) -> warning(Error((FSComp.SR.fsiInvalidDirective(c, String.concat " " arg)), m)) istate, Completed None ) diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 66289f3cf55..90a40745e4c 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -649,11 +649,14 @@ hashDirectiveArgs: /* One argument to a #directive */ -hashDirectiveArg: +hashDirectiveArg: | string - { let s, _ = $1 - s } - + { let s, kind = $1 + ParsedHashDirectiveArgument.String (s, kind, lhs parseState) } + | sourceIdentifier + { let c,v = $1 + ParsedHashDirectiveArgument.SourceIdentifier (c, v, lhs parseState) } + /*--------------------------------------------------------------------------*/ /* F# Language Proper - signature files */ diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index af765bcc81f..b8b5c504c06 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -5353,16 +5353,45 @@ FSharp.Compiler.Syntax.LongIdentWithDots: Microsoft.FSharp.Collections.FSharpLis FSharp.Compiler.Syntax.LongIdentWithDots: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range] get_dotRanges() FSharp.Compiler.Syntax.LongIdentWithDots: System.String ToString() FSharp.Compiler.Syntax.ParsedHashDirective -FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Syntax.ParsedHashDirective NewParsedHashDirective(System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Syntax.ParsedHashDirective NewParsedHashDirective(System.String, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.ParsedHashDirective: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.ParsedHashDirective: Int32 Tag FSharp.Compiler.Syntax.ParsedHashDirective: Int32 get_Tag() -FSharp.Compiler.Syntax.ParsedHashDirective: Microsoft.FSharp.Collections.FSharpList`1[System.String] args -FSharp.Compiler.Syntax.ParsedHashDirective: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_args() +FSharp.Compiler.Syntax.ParsedHashDirective: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument] args +FSharp.Compiler.Syntax.ParsedHashDirective: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirectiveArgument] get_args() FSharp.Compiler.Syntax.ParsedHashDirective: System.String ToString() FSharp.Compiler.Syntax.ParsedHashDirective: System.String get_ident() FSharp.Compiler.Syntax.ParsedHashDirective: System.String ident +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier: System.String constant +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier: System.String get_constant() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier: System.String get_value() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier: System.String value +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String: FSharp.Compiler.Syntax.SynStringKind get_stringKind() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String: FSharp.Compiler.Syntax.SynStringKind stringKind +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String: System.String get_value() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String: System.String value +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+Tags: Int32 SourceIdentifier +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+Tags: Int32 String +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Boolean IsSourceIdentifier +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Boolean IsString +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Boolean get_IsSourceIdentifier() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Boolean get_IsString() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Syntax.ParsedHashDirectiveArgument NewSourceIdentifier(System.String, System.String, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Syntax.ParsedHashDirectiveArgument NewString(System.String, FSharp.Compiler.Syntax.SynStringKind, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+SourceIdentifier +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+String +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Syntax.ParsedHashDirectiveArgument+Tags +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: FSharp.Compiler.Text.Range get_Range() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 Tag +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: Int32 get_Tag() +FSharp.Compiler.Syntax.ParsedHashDirectiveArgument: System.String ToString() FSharp.Compiler.Syntax.ParsedImplFile FSharp.Compiler.Syntax.ParsedImplFile: FSharp.Compiler.Syntax.ParsedImplFile NewParsedImplFile(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedHashDirective], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.ParsedImplFileFragment]) FSharp.Compiler.Syntax.ParsedImplFile: Int32 Tag diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 7d94a48b38d..a3e642b70d8 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -1153,4 +1153,61 @@ type Bird = assertRange (3, 4) (6, 50) getter.Range assertRange (3, 4) (6, 23) mb2 assertRange (3, 4) (6, 50) setter.Range + | _ -> Assert.Fail "Could not get valid AST" + +module ParsedHashDirective = + [] + let ``SourceIdentifier as ParsedHashDirectiveArgument`` () = + let parseResults = + getParseResults + "#I __SOURCE_DIRECTORY__" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.HashDirective(ParsedHashDirective("I", [ ParsedHashDirectiveArgument.SourceIdentifier(c,_,m) ] , _), _) + ]) ])) -> + Assert.AreEqual("__SOURCE_DIRECTORY__", c) + assertRange (1, 3) (1, 23) m + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Regular String as ParsedHashDirectiveArgument`` () = + let parseResults = + getParseResults + "#I \"/tmp\"" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.HashDirective(ParsedHashDirective("I", [ ParsedHashDirectiveArgument.String(v, SynStringKind.Regular, m) ] , _), _) + ]) ])) -> + Assert.AreEqual("/tmp", v) + assertRange (1, 3) (1, 9) m + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Verbatim String as ParsedHashDirectiveArgument`` () = + let parseResults = + getParseResults + "#I @\"C:\\Temp\"" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.HashDirective(ParsedHashDirective("I", [ ParsedHashDirectiveArgument.String(v, SynStringKind.Verbatim, m) ] , _), _) + ]) ])) -> + Assert.AreEqual("C:\\Temp", v) + assertRange (1, 3) (1, 13) m + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Triple quote String as ParsedHashDirectiveArgument`` () = + let parseResults = + getParseResults + "#nowarn \"\"\"40\"\"\"" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.HashDirective(ParsedHashDirective("nowarn", [ ParsedHashDirectiveArgument.String(v, SynStringKind.TripleQuote, m) ] , _), _) + ]) ])) -> + Assert.AreEqual("40", v) + assertRange (1, 8) (1, 16) m | _ -> Assert.Fail "Could not get valid AST" \ No newline at end of file