+
+
+
+
As established in Tutorial: Expressions, the AST held in a ParsedInput
value
+can be traversed by a set of recursive functions. It can be tedious and error-prone to write these functions from scratch every time, though,
+so the ParsedInput
module
+exposes a number of functions to make common operations easier.
+
For example:
+
+-
+
ParsedInput.exists
+
+- May be used by tooling to determine whether the user's cursor is in a certain context, e.g., to determine whether to offer a certain tooling action.
+
+
+-
+
ParsedInput.fold
+
+- May be used when writing analyzers to collect diagnostic information for an entire source file.
+
+
+-
+
ParsedInput.foldWhile
+
+- Like
fold
but supports stopping traversal early.
+
+
+-
+
ParsedInput.tryNode
+
+- May be used by tooling to get the last (deepest) node under the user's cursor.
+
+
+-
+
ParsedInput.tryPick
+
+- May be used by tooling to find the first (shallowest) matching node near the user's cursor.
+
+
+-
+
ParsedInput.tryPickLast
+
+- May be used by tooling to find the last (deepest) matching node near the user's cursor.
+
+
+
+
+
While the ParsedInput
module functions are usually the simplest way to meet most needs,
+there is also a SyntaxVisitorBase
-based API that can
+provide somewhat more fine-grained control over syntax traversal for a subset of use-cases at the expense of a bit more
+ceremony and complexity.
+
+
Let's start by introducing a helper function for constructing an AST from source code so we can run through some real examples:
+
#r "FSharp.Compiler.Service.dll"
+open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.Text
+open FSharp.Compiler.Syntax
+
+let checker = FSharpChecker.Create()
+
+/// A helper for constructing a `ParsedInput` from a code snippet.
+let mkTree codeSample =
+ let parseFileResults =
+ checker.ParseFile(
+ "FileName.fs",
+ SourceText.ofString codeSample,
+ { FSharpParsingOptions.Default with SourceFiles = [| "FileName.fs" |] }
+ )
+ |> Async.RunSynchronously
+
+ parseFileResults.ParseTree
+
+
+
Now consider the following code sample:
+
let brokenTypeDefn = """
+module Lib
+
+// Whoops, we forgot the equals sign.
+type T { A: int; B: int }
+"""
+
+
Let's say we have a code fix for adding an equals sign to a type definition that's missing one—like the one above.
+We want to offer the fix when the user's cursor is inside of—or just after—the broken type definition.
+
We can determine this by using ParsedInput.exists
and passing in the position of the user's cursor:
+
// type T { A: int; B: int }
+// ···········↑
+let posInMiddleOfTypeDefn = Position.mkPos 5 12
+
+
Given that cursor position, all we need to do is find a SynTypeDefn
node:
+
let isPosInTypeDefn = // true.
+ (posInMiddleOfTypeDefn, mkTree brokenTypeDefn)
+ ||> ParsedInput.exists (fun _path node ->
+ match node with
+ | SyntaxNode.SynTypeDefn _ -> true
+ | _ -> false)
+
+
If the position passed into ParsedInput.exists
is not contained in any node in the given AST,
+but rather is below or to the right of all nodes, ParsedInput.exists
will fall back to exploring the nearest branch above
+and/or to the left. This is useful because the user's cursor may lie beyond the range of all nodes.
+
// type T { A: int; B: int }
+// ··························↑
+let posAfterTypeDefn = Position.mkPos 5 28
+
+
Our function still returns true
if the cursor is past the end of the type definition node itself:
+
let isPosInTypeDefn' = // Still true.
+ (posAfterTypeDefn, mkTree brokenTypeDefn)
+ ||> ParsedInput.exists (fun _path node ->
+ match node with
+ | SyntaxNode.SynTypeDefn _ -> true
+ | _ -> false)
+
+
+
ParsedInput.fold
can be useful when writing an analyzer to collect diagnostics from entire input files.
+
Take this code that has unnecessary parentheses in both patterns and expressions:
+
let unnecessaryParentheses = """
+let (x) = (id (3))
+"""
+
+
We can gather the ranges of all unnecessary parentheses like this:
+
open System.Collections.Generic
+
+module HashSet =
+ let add item (set: HashSet<_>) =
+ ignore (set.Add item)
+ set
+
+let unnecessaryParenthesesRanges =
+ (HashSet Range.comparer, mkTree unnecessaryParentheses) ||> ParsedInput.fold (fun ranges path node ->
+ match node with
+ | SyntaxNode.SynExpr(SynExpr.Paren(expr = inner; rightParenRange = Some _; range = range)) when
+ not (SynExpr.shouldBeParenthesizedInContext getLineStr path inner)
+ ->
+ ranges |> HashSet.add range
+
+ | SyntaxNode.SynPat(SynPat.Paren(inner, range)) when
+ not (SynPat.shouldBeParenthesizedInContext path inner)
+ ->
+ ranges |> HashSet.add range
+
+ | _ ->
+ ranges)
+
+
+
Sometimes, we might just want to get whatever node is directly at a given position—for example, if the user's
+cursor is on an argument of a function being applied, we can find the node representing the argument and use its path
+to backtrack and find the function's name.
+
let functionApplication = """
+f x y
+"""
+
+
If we have our cursor on y
:
+
// f x y
+// ·····↑
+let posOnY = Position.mkPos 2 5
+
+
The syntax node representing the function f
technically contains the cursor's position,
+but ParsedInput.tryNode
will keep diving until it finds the deepest node containing the position.
+
We can thus get the node representing y
and its ancestors (the path
) like this:
+
let yAndPath = // Some (SynExpr (Ident y), [SynExpr (App …); …])
+ mkTree functionApplication
+ |> ParsedInput.tryNode posOnY
+
+
Note that, unlike ParsedInput.exists
, ParsedInput.tryPick
, and ParsedInput.tryPickLast
,
+ParsedInput.tryNode
does not fall back to the nearest branch above or to the left.
+
// f x y
+// ······↑
+let posAfterY = Position.mkPos 2 8
+
+
If we take the same code snippet but pass in a position after y
,
+we get no node:
+
let nope = // None.
+ mkTree functionApplication
+ |> ParsedInput.tryNode posAfterY
+
+
+
Now imagine that we have a code fix for converting a record construction expression into an anonymous record construction
+expression when there is no record type in scope whose fields match.
+
let recordExpr = """
+let r = { A = 1; B = 2 }
+"""
+
+
We can offer this fix when the user's cursor is inside of a record expression by
+using ParsedInput.tryPick
to return the surrounding record expression's range, if any.
+
// let r = { A = 1; B = 2 }
+// ······················↑
+let posInRecordExpr = Position.mkPos 2 25
+
+
Here, even though ParsedInput.tryPick
will try to cleave to the given position by default,
+we want to verify that the record expression node that we've come across actually contains the position,
+since, like ParsedInput.exists
, ParsedInput.tryPick
will also fall back to the nearest branch above and/or
+to the left if no node actually contains the position. In this case, we don't want to offer the code fix
+if the user's cursor isn't actually inside of the record expression.
+
let recordExprRange = // Some (2,8--2,24).
+ (posInRecordExpr, mkTree recordExpr)
+ ||> ParsedInput.tryPick (fun _path node ->
+ match node with
+ | SyntaxNode.SynExpr(SynExpr.Record(range = range)) when
+ Range.rangeContainsPos range posInRecordExpr
+ -> Some range
+ | _ -> None)
+
+
We might also sometimes want to make use of the path
parameter. Take this simple function definition:
+
let myFunction = """
+module Lib
+
+let myFunction paramOne paramTwo =
+ ()
+"""
+
+
Imagine we want to grab the myFunction
name from the headPat
in the SynBinding
.
+
We can write a function to match the node we're looking for—and not match anything we're not looking for (like the argument patterns)—by taking its path into account:
+
let myFunctionId = // Some "myFunction".
+ (Position.pos0, mkTree myFunction)
+ ||> ParsedInput.tryPick (fun path node ->
+ // Match on the node and the path (the node's ancestors) to see whether:
+ // 1. The node is a pattern.
+ // 2. The pattern is a long identifier pattern.
+ // 3. The pattern's parent node (the head of the path) is a binding.
+ match node, path with
+ | SyntaxNode.SynPat(SynPat.LongIdent(longDotId = SynLongIdent(id = [ ident ]))),
+ SyntaxNode.SynBinding _ :: _ ->
+ // We have found what we're looking for.
+ Some ident.idText
+ | _ ->
+ // If the node or its context don't match,
+ // we continue.
+ None)
+
+
Instead of traversing manually from ParsedInput
to SynModuleOrNamespace
to SynModuleDecl.Let
to SynBinding
to SynPat
, we leverage the default navigation that happens in ParsedInput.tryPick
.
+ParsedInput.tryPick
will short-circuit once we have indicated that we have found what we're looking for by returning Some value
.
+
Our code sample of course only had one let-binding and thus we didn't need to specify any further logic to differentiate between bindings.
+
Let's consider a second example involving multiple let-bindings:
+
let multipleLetsInModule = """
+module X
+
+let a = 0
+let b = 1
+let c = 2
+"""
+
+
In this case, we know the user's cursor inside an IDE is placed after c
, and we are interested in the body expression of the last let-binding.
+
// …
+// let c = 2
+// ·····↑
+let posInLastLet = Position.mkPos 6 5
+
+
Thanks to the cursor position we passed in, we do not need to write any code to exclude the expressions of the sibling let-bindings.
+ParsedInput.tryPick
will check whether the current position is inside any given syntax node before drilling deeper.
+
let bodyOfLetContainingPos = // Some (Const (Int32 2, (6,8--6,9))).
+ (posInLastLet, mkTree multipleLetsInModule)
+ ||> ParsedInput.tryPick (fun _path node ->
+ match node with
+ | SyntaxNode.SynBinding(SynBinding(expr = e)) -> Some e
+ | _ -> None)
+
+
As noted above, ParsedInput.tryPick
will short-circuit at the first matching node.
+ParsedInput.tryPickLast
can be used to get the last matching node that contains a given position.
+
Take this example of multiple nested modules:
+
let nestedModules = """
+module M
+
+module N =
+ module O =
+ module P = begin end
+"""
+
+
By using ParsedInput.tryPick
, we'll get the name of the outermost nested module even if we pass in a position inside the innermost,
+since the innermost is contained within the outermost.
+
This position is inside module P
, which is nested inside of module O
, which is nested inside of module N
,
+which is nested inside of top-level module M
:
+
// module M
+//
+// module N =
+// module O =
+// module P = begin end
+// ···························↑
+let posInsideOfInnermostNestedModule = Position.mkPos 6 28
+
+
ParsedInput.tryPick
short-circuits on the first match, and since module N
is the first
+nested module whose range contains position (6, 28), that's the result we get.
+
let outermostNestedModule = // Some ["N"].
+ (posInsideOfInnermostNestedModule, mkTree nestedModules)
+ ||> ParsedInput.tryPick (fun _path node ->
+ match node with
+ | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longId))) ->
+ Some [for ident in longId -> ident.idText]
+ | _ -> None)
+
+
+
If however we use the same code snippet and pass the same position into ParsedInput.tryPickLast
,
+we can get the name of the last (deepest or innermost) matching node:
+
let innermostNestedModule = // Some ["P"].
+ (posInsideOfInnermostNestedModule, mkTree nestedModules)
+ ||> ParsedInput.tryPickLast (fun _path node ->
+ match node with
+ | SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longId))) ->
+ Some [for ident in longId -> ident.idText]
+ | _ -> None)
+
+
If we want the next-to-innermost nested module, we can do likewise but make use of the path
parameter:
+
let nextToInnermostNestedModule = // Some ["O"].
+ (posInsideOfInnermostNestedModule, mkTree nestedModules)
+ ||> ParsedInput.tryPickLast (fun path node ->
+ match node, path with
+ | SyntaxNode.SynModule(SynModuleDecl.NestedModule _),
+ SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo = SynComponentInfo(longId = longId))) :: _ ->
+ Some [for ident in longId -> ident.idText]
+ | _ -> None)
+
+
+
Consider again the following code sample:
+
let codeSample = """
+module Lib
+
+let myFunction paramOne paramTwo =
+ ()
+"""
+
+
Imagine we wish to grab the myFunction
name from the headPat
in the SynBinding.
+
We can create a visitor to traverse the tree and find the function name:
+
let visitor =
+ { new SyntaxVisitorBase<string>() with
+ override this.VisitPat(path, defaultTraverse, synPat) =
+ // First check if the pattern is what we are looking for.
+ match synPat with
+ | SynPat.LongIdent(longDotId = SynLongIdent(id = [ ident ])) ->
+ // Next we can check if the current path of visited nodes, matches our expectations.
+ // The path will contain all the ancestors of the current node.
+ match path with
+ // The parent node of `synPat` should be a `SynBinding`.
+ | SyntaxNode.SynBinding _ :: _ ->
+ // We return a `Some` option to indicate we found what we are looking for.
+ Some ident.idText
+ // If the parent is something else, we can skip it here.
+ | _ -> None
+ | _ -> None }
+
+let result = SyntaxTraversal.Traverse(Position.pos0, mkTree codeSample, visitor) // Some "myFunction"
+
+
Instead of traversing manually from ParsedInput
to SynModuleOrNamespace
to SynModuleDecl.Let
to SynBinding
to SynPat
, we leverage the default navigation that happens in SyntaxTraversal.Traverse
.
+A SyntaxVisitorBase
will shortcut all other code paths once a single VisitXYZ
override has found anything.
+
Our code sample of course only had one let binding and thus we didn't need to specify any further logic whether to differentiate between multiple bindings.
+
+
Let's now consider a second example where we know the user's cursor inside an IDE is placed after c
and we are interested in the body expression of the let binding.
+
let secondCodeSample = """
+module X
+
+let a = 0
+let b = 1
+let c = 2
+"""
+
+let secondVisitor =
+ { new SyntaxVisitorBase<SynExpr>() with
+ override this.VisitBinding(path, defaultTraverse, binding) =
+ match binding with
+ | SynBinding(expr = e) -> Some e }
+
+let cursorPos = Position.mkPos 6 5
+
+let secondResult =
+ SyntaxTraversal.Traverse(cursorPos, mkTree secondCodeSample, secondVisitor) // Some (Const (Int32 2, (6,8--6,9)))
+
+
Due to our passed cursor position, we did not need to write any code to exclude the expressions of the other let bindings.
+SyntaxTraversal.Traverse
will check whether the current position is inside any syntax node before drilling deeper.
+
+
Lastly, some VisitXYZ
overrides can contain a defaultTraverse. This helper allows you to continue the default traversal when you currently hit a node that is not of interest.
+Consider 1 + 2 + 3 + 4
, this will be reflected in a nested infix application expression.
+If the cursor is at the end of the entire expression, we can grab the value of 4
using the following visitor:
+
let thirdCodeSample = "let sum = 1 + 2 + 3 + 4"
+
+(*
+AST will look like:
+
+Let
+ (false,
+ [SynBinding
+ (None, Normal, false, false, [],
+ PreXmlDoc ((1,0), Fantomas.FCS.Xml.XmlDocCollector),
+ SynValData
+ (None, SynValInfo ([], SynArgInfo ([], false, None)), None,
+ None),
+ Named (SynIdent (sum, None), false, None, (1,4--1,7)), None,
+ App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true,
+ LongIdent
+ (false,
+ SynLongIdent
+ ([op_Addition], [], [Some (OriginalNotation "+")]),
+ None, (1,20--1,21)),
+ App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true,
+ LongIdent
+ (false,
+ SynLongIdent
+ ([op_Addition], [],
+ [Some (OriginalNotation "+")]), None,
+ (1,16--1,17)),
+ App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true,
+ LongIdent
+ (false,
+ SynLongIdent
+ ([op_Addition], [],
+ [Some (OriginalNotation "+")]), None,
+ (1,12--1,13)),
+ Const (Int32 1, (1,10--1,11)), (1,10--1,13)),
+ Const (Int32 2, (1,14--1,15)), (1,10--1,15)),
+ (1,10--1,17)), Const (Int32 3, (1,18--1,19)),
+ (1,10--1,19)), (1,10--1,21)),
+ Const (Int32 4, (1,22--1,23)), (1,10--1,23)), (1,4--1,7),
+ Yes (1,0--1,23), { LeadingKeyword = Let (1,0--1,3)
+ InlineKeyword = None
+ EqualsRange = Some (1,8--1,9) })
+*)
+
+let thirdCursorPos = Position.mkPos 1 22
+
+let thirdVisitor =
+ { new SyntaxVisitorBase<int>() with
+ override this.VisitExpr(path, traverseSynExpr, defaultTraverse, synExpr) =
+ match synExpr with
+ | SynExpr.Const (constant = SynConst.Int32 v) -> Some v
+ // We do want to continue to traverse when nodes like `SynExpr.App` are found.
+ | otherExpr -> defaultTraverse otherExpr }
+
+let thirdResult =
+ SyntaxTraversal.Traverse(cursorPos, mkTree thirdCodeSample, thirdVisitor) // Some 4
+
+
defaultTraverse
is especially useful when you do not know upfront what syntax tree you will be walking.
+This is a common case when dealing with IDE tooling. You won't know what actual code the end-user is currently processing.
+
Note: SyntaxVisitorBase is designed to find a single value inside a tree!
+This is not an ideal solution when you are interested in all nodes of certain shape.
+It will always verify if the given cursor position is still matching the range of the node.
+As a fallback the first branch will be explored when you pass Position.pos0
.
+By design, it is meant to find a single result.
+
+
Multiple items
namespace FSharp
--------------------
namespace Microsoft.FSharp
+
namespace FSharp.Compiler
+
namespace FSharp.Compiler.CodeAnalysis
+
namespace FSharp.Compiler.Text
+
namespace FSharp.Compiler.Syntax
+
val checker: FSharpChecker
+
type FSharpChecker =
+ member CheckFileInProject: parseResults: FSharpParseFileResults * fileName: string * fileVersion: int * sourceText: ISourceText * options: FSharpProjectOptions * ?userOpName: string -> Async<FSharpCheckFileAnswer>
+ member ClearCache: options: FSharpProjectOptions seq * ?userOpName: string -> unit + 1 overload
+ member ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients: unit -> unit
+ member Compile: argv: string array * ?userOpName: string -> Async<FSharpDiagnostic array * int>
+ member FindBackgroundReferencesInFile: fileName: string * options: FSharpProjectOptions * symbol: FSharpSymbol * ?canInvalidateProject: bool * [<Experimental ("This FCS API is experimental and subject to change.")>] ?fastCheck: bool * ?userOpName: string -> Async<range seq> + 1 overload
+ member GetBackgroundCheckResultsForFileInProject: fileName: string * options: FSharpProjectOptions * ?userOpName: string -> Async<FSharpParseFileResults * FSharpCheckFileResults>
+ member GetBackgroundParseResultsForFileInProject: fileName: string * options: FSharpProjectOptions * ?userOpName: string -> Async<FSharpParseFileResults>
+ member GetBackgroundSemanticClassificationForFile: fileName: string * options: FSharpProjectOptions * ?userOpName: string -> Async<SemanticClassificationView option> + 1 overload
+ member GetParsingOptionsFromCommandLineArgs: sourceFiles: string list * argv: string list * ?isInteractive: bool * ?isEditing: bool -> FSharpParsingOptions * FSharpDiagnostic list + 1 overload
+ member GetParsingOptionsFromProjectOptions: options: FSharpProjectOptions -> FSharpParsingOptions * FSharpDiagnostic list
+ ...
<summary>
+ Used to parse and check F# source code.
+</summary>
+
static member FSharpChecker.Create: ?projectCacheSize: int * ?keepAssemblyContents: bool * ?keepAllBackgroundResolutions: bool * ?legacyReferenceResolver: LegacyReferenceResolver * ?tryGetMetadataSnapshot: FSharp.Compiler.AbstractIL.ILBinaryReader.ILReaderTryGetMetadataSnapshot * ?suggestNamesForErrors: bool * ?keepAllBackgroundSymbolUses: bool * ?enableBackgroundItemKeyStoreAndSemanticClassification: bool * ?enablePartialTypeChecking: bool * ?parallelReferenceResolution: bool * ?captureIdentifiersWhenParsing: bool * [<Experimental ("This parameter is experimental and likely to be removed in the future.")>] ?documentSource: DocumentSource * [<Experimental ("This parameter is experimental and likely to be removed in the future.")>] ?useSyntaxTreeCache: bool * [<Experimental ("This parameter is experimental and likely to be removed in the future.")>] ?useTransparentCompiler: bool -> FSharpChecker
+
val mkTree: codeSample: string -> ParsedInput
A helper for constructing a `ParsedInput` from a code snippet.
+
val codeSample: string
+
val parseFileResults: FSharpParseFileResults
+
member FSharpChecker.ParseFile: fileName: string * projectSnapshot: FSharpProjectSnapshot * ?userOpName: string -> Async<FSharpParseFileResults>
member FSharpChecker.ParseFile: fileName: string * sourceText: ISourceText * options: FSharpParsingOptions * ?cache: bool * ?userOpName: string -> Async<FSharpParseFileResults>
+
module SourceText
+
+from FSharp.Compiler.Text
<summary>
+ Functions related to ISourceText objects
+</summary>
+
val ofString: string -> ISourceText
<summary>
+ Creates an ISourceText object from the given string
+</summary>
+
type FSharpParsingOptions =
+ {
+ SourceFiles: string array
+ ApplyLineDirectives: bool
+ ConditionalDefines: string list
+ DiagnosticOptions: FSharpDiagnosticOptions
+ LangVersionText: string
+ IsInteractive: bool
+ IndentationAwareSyntax: bool option
+ StrictIndentation: bool option
+ CompilingFSharpCore: bool
+ IsExe: bool
+ }
+ static member Default: FSharpParsingOptions
<summary>
+ Options used to determine active --define conditionals and other options relevant to parsing files in a project
+</summary>
+
property FSharpParsingOptions.Default: FSharpParsingOptions with get
+
Multiple items
type Async =
+ static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
+ static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
+ static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async<bool>
+ static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload
+ static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async<bool>
+ static member CancelDefaultToken: unit -> unit
+ static member Catch: computation: Async<'T> -> Async<Choice<'T,exn>>
+ static member Choice: computations: Async<'T option> seq -> Async<'T option>
+ static member FromBeginEnd: beginAction: (AsyncCallback * obj -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads
+ static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
+ ...
--------------------
type Async<'T>
+
static member Async.RunSynchronously: computation: Async<'T> * ?timeout: int * ?cancellationToken: System.Threading.CancellationToken -> 'T
+
property FSharpParseFileResults.ParseTree: ParsedInput with get
<summary>
+ The syntax tree resulting from the parse
+</summary>
+
val brokenTypeDefn: string
+
val posInMiddleOfTypeDefn: pos
+
Multiple items
module Position
+
+from FSharp.Compiler.Text
--------------------
[<Struct>]
+type Position =
+ member Column: int
+ member Line: int
<summary>
+ Represents a position in a file
+</summary>
+
val mkPos: line: int -> column: int -> pos
<summary>
+ Create a position for the given line and column
+</summary>
+
val isPosInTypeDefn: bool
+
Multiple items
module ParsedInput
+
+from FSharp.Compiler.Syntax
<summary>
+ Holds operations for working with the
+ untyped abstract syntax tree (<see cref="T:FSharp.Compiler.Syntax.ParsedInput" />).
+ </summary>
--------------------
type ParsedInput =
+ | ImplFile of ParsedImplFileInput
+ | SigFile of ParsedSigFileInput
+ member FileName: string
+ member Identifiers: Set<string>
+ member QualifiedName: QualifiedNameOfFile
+ member Range: range
+ member ScopedPragmas: ScopedPragma list
<summary>
+ Represents the syntax tree for a parsed implementation or signature file
+</summary>
+
val exists: predicate: (SyntaxVisitorPath -> SyntaxNode -> bool) -> position: pos -> parsedInput: ParsedInput -> bool
<summary>
+ Applies the given predicate to each node of the AST and its context (path)
+ down to a given position, returning true if a matching node is found, otherwise false.
+ Traversal is short-circuited if no matching node is found through the given position.
+ </summary>
<param name="predicate">The predicate to match each node against.</param>
<param name="position">The position in the input file down to which to apply the function.</param>
<param name="parsedInput">The AST to search.</param>
<returns>True if a matching node is found, or false if no matching node is found.</returns>
<example><code lang="fsharp">
+ let isInTypeDefn =
+ (pos, parsedInput)
+ ||> ParsedInput.exists (fun _path node ->
+ match node with
+ | SyntaxNode.SynTypeDefn _ -> true
+ | _ -> false)
+ </code></example>
+
val _path: SyntaxVisitorPath
+
val node: SyntaxNode
+
Multiple items
module SyntaxNode
+
+from FSharp.Compiler.Syntax
<summary>
+ Holds operations for working with <see cref="T:FSharp.Compiler.Syntax.SyntaxNode" />s
+ in the untyped abstract syntax tree (AST).
+ </summary>
--------------------
type SyntaxNode =
+ | SynPat of SynPat
+ | SynType of SynType
+ | SynExpr of SynExpr
+ | SynModule of SynModuleDecl
+ | SynModuleOrNamespace of SynModuleOrNamespace
+ | SynTypeDefn of SynTypeDefn
+ | SynMemberDefn of SynMemberDefn
+ | SynMatchClause of SynMatchClause
+ | SynBinding of SynBinding
+ | SynModuleOrNamespaceSig of SynModuleOrNamespaceSig
+ ...
+ member Range: range
<summary>
+ Represents a major syntax node in the untyped abstract syntax tree.
+</summary>
+
union case SyntaxNode.SynTypeDefn: SynTypeDefn -> SyntaxNode
+
val posAfterTypeDefn: pos
+
val isPosInTypeDefn': bool
+
type SynExpr =
+ | Paren of expr: SynExpr * leftParenRange: range * rightParenRange: range option * range: range
+ | Quote of operator: SynExpr * isRaw: bool * quotedExpr: SynExpr * isFromQueryExpression: bool * range: range
+ | Const of constant: SynConst * range: range
+ | Typed of expr: SynExpr * targetType: SynType * range: range
+ | Tuple of isStruct: bool * exprs: SynExpr list * commaRanges: range list * range: range
+ | AnonRecd of isStruct: bool * copyInfo: (SynExpr * BlockSeparator) option * recordFields: (SynLongIdent * range option * SynExpr) list * range: range * trivia: SynExprAnonRecdTrivia
+ | ArrayOrList of isArray: bool * exprs: SynExpr list * range: range
+ | Record of baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option * copyInfo: (SynExpr * BlockSeparator) option * recordFields: SynExprRecordField list * range: range
+ | New of isProtected: bool * targetType: SynType * expr: SynExpr * range: range
+ | ObjExpr of objType: SynType * argOptions: (SynExpr * Ident option) option * withKeyword: range option * bindings: SynBinding list * members: SynMemberDefns * extraImpls: SynInterfaceImpl list * newExprRange: range * range: range
+ ...
+ member IsArbExprAndThusAlreadyReportedError: bool
+ member Range: range
+ member RangeOfFirstPortion: range
+ member RangeWithoutAnyExtraDot: range
<summary>
+ Represents a syntax tree for F# expressions
+</summary>
+
val shouldBeParenthesizedInContext: getLineStr: (int -> string) -> path: SyntaxVisitorPath -> expr: SynExpr -> bool
+
val getLineStr: (int -> string)
+
Multiple items
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> =
+ int
+
Multiple items
val string: value: 'T -> string
--------------------
type string = System.String
+
val path: SyntaxVisitorPath
+
type SyntaxVisitorPath = SyntaxNode list
<summary>
+ Represents the set of ancestor nodes traversed before reaching
+ the current node in a traversal of the untyped abstract syntax tree.
+</summary>
+
val expr: SynExpr
+
type bool = System.Boolean
+
val failwith: message: string -> 'T
+
type SynPat =
+ | Const of constant: SynConst * range: range
+ | Wild of range: range
+ | Named of ident: SynIdent * isThisVal: bool * accessibility: SynAccess option * range: range
+ | Typed of pat: SynPat * targetType: SynType * range: range
+ | Attrib of pat: SynPat * attributes: SynAttributes * range: range
+ | Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia
+ | ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia
+ | Ands of pats: SynPat list * range: range
+ | As of lhsPat: SynPat * rhsPat: SynPat * range: range
+ | LongIdent of longDotId: SynLongIdent * extraId: Ident option * typarDecls: SynValTyparDecls option * argPats: SynArgPats * accessibility: SynAccess option * range: range
+ ...
+ member Range: range
<summary>
+ Represents a syntax tree for an F# pattern
+</summary>
+
val shouldBeParenthesizedInContext: path: SyntaxVisitorPath -> pat: SynPat -> bool
+
val pat: SynPat
+
val getLineStr: line: int -> string
+
val line: int
+
val unnecessaryParentheses: string
+
namespace System
+
namespace System.Collections
+
namespace System.Collections.Generic
+
Multiple items
type HashSet<'T> =
+ interface ICollection<'T>
+ interface IEnumerable<'T>
+ interface IEnumerable
+ interface IReadOnlyCollection<'T>
+ interface ISet<'T>
+ interface IReadOnlySet<'T>
+ interface IDeserializationCallback
+ interface ISerializable
+ new: unit -> unit + 5 overloads
+ member Add: item: 'T -> bool
+ ...
<summary>Represents a set of values.</summary>
<typeparam name="T">The type of elements in the hash set.</typeparam>
--------------------
HashSet() : HashSet<'T>
HashSet(collection: IEnumerable<'T>) : HashSet<'T>
HashSet(comparer: IEqualityComparer<'T>) : HashSet<'T>
HashSet(capacity: int) : HashSet<'T>
HashSet(collection: IEnumerable<'T>, comparer: IEqualityComparer<'T>) : HashSet<'T>
HashSet(capacity: int, comparer: IEqualityComparer<'T>) : HashSet<'T>
+
val add: item: 'a -> set: HashSet<'a> -> HashSet<'a>
+
val item: 'a
+
val set: HashSet<'a>
+
val ignore: value: 'T -> unit
+
HashSet.Add(item: 'a) : bool
+
val unnecessaryParenthesesRanges: HashSet<range>
+
Multiple items
module Range
+
+from FSharp.Compiler.Text
--------------------
[<Struct>]
+type Range =
+ member End: pos
+ member EndColumn: int
+ member EndLine: int
+ member EndRange: range
+ member FileName: string
+ member IsSynthetic: bool
+ member Start: pos
+ member StartColumn: int
+ member StartLine: int
+ member StartRange: range
+ ...
<summary>
+ Represents a range within a file
+</summary>
+
val comparer: IEqualityComparer<range>
<summary>
+ Equality comparer for range.
+</summary>
+
val fold: folder: ('State -> SyntaxVisitorPath -> SyntaxNode -> 'State) -> state: 'State -> parsedInput: ParsedInput -> 'State
<summary>
+ Applies a function to each node of the AST and its context (path),
+ threading an accumulator through the computation.
+ </summary>
<param name="folder">The function to use to update the state given each node and its context.</param>
<param name="state">The initial state.</param>
<param name="parsedInput">The AST to fold over.</param>
<returns>The final state.</returns>
<example><code lang="fsharp">
+ let unnecessaryParentheses =
+ (HashSet Range.comparer, parsedInput) ||> ParsedInput.fold (fun acc path node ->
+ match node with
+ | SyntaxNode.SynExpr (SynExpr.Paren (expr = inner; rightParenRange = Some _; range = range)) when
+ not (SynExpr.shouldBeParenthesizedInContext getLineString path inner)
+ ->
+ ignore (acc.Add range)
+ acc
+
+ | SyntaxNode.SynPat (SynPat.Paren (inner, range)) when
+ not (SynPat.shouldBeParenthesizedInContext path inner)
+ ->
+ ignore (acc.Add range)
+ acc
+
+ | _ -> acc)
+ </code></example>
+
val ranges: HashSet<range>
+
union case SyntaxNode.SynExpr: SynExpr -> SyntaxNode
+
Multiple items
module SynExpr
+
+from Untypedtree-apis
--------------------
type SynExpr =
+ | Paren of expr: SynExpr * leftParenRange: range * rightParenRange: range option * range: range
+ | Quote of operator: SynExpr * isRaw: bool * quotedExpr: SynExpr * isFromQueryExpression: bool * range: range
+ | Const of constant: SynConst * range: range
+ | Typed of expr: SynExpr * targetType: SynType * range: range
+ | Tuple of isStruct: bool * exprs: SynExpr list * commaRanges: range list * range: range
+ | AnonRecd of isStruct: bool * copyInfo: (SynExpr * BlockSeparator) option * recordFields: (SynLongIdent * range option * SynExpr) list * range: range * trivia: SynExprAnonRecdTrivia
+ | ArrayOrList of isArray: bool * exprs: SynExpr list * range: range
+ | Record of baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option * copyInfo: (SynExpr * BlockSeparator) option * recordFields: SynExprRecordField list * range: range
+ | New of isProtected: bool * targetType: SynType * expr: SynExpr * range: range
+ | ObjExpr of objType: SynType * argOptions: (SynExpr * Ident option) option * withKeyword: range option * bindings: SynBinding list * members: SynMemberDefns * extraImpls: SynInterfaceImpl list * newExprRange: range * range: range
+ ...
+ member IsArbExprAndThusAlreadyReportedError: bool
+ member Range: range
+ member RangeOfFirstPortion: range
+ member RangeWithoutAnyExtraDot: range
<summary>
+ Represents a syntax tree for F# expressions
+</summary>
+
union case SynExpr.Paren: expr: SynExpr * leftParenRange: range * rightParenRange: range option * range: range -> SynExpr
<summary>
+ F# syntax: (expr)
+
+ Parenthesized expressions. Kept in AST to distinguish A.M((x, y))
+ from A.M(x, y), among other things.
+</summary>
+
val inner: SynExpr
+
union case Option.Some: Value: 'T -> Option<'T>
+
Multiple items
val range: range
--------------------
type range = Range
<summary>
+ Represents a range within a file
+</summary>
+
union case SyntaxNode.SynPat: SynPat -> SyntaxNode
+
Multiple items
module SynPat
+
+from Untypedtree-apis
--------------------
type SynPat =
+ | Const of constant: SynConst * range: range
+ | Wild of range: range
+ | Named of ident: SynIdent * isThisVal: bool * accessibility: SynAccess option * range: range
+ | Typed of pat: SynPat * targetType: SynType * range: range
+ | Attrib of pat: SynPat * attributes: SynAttributes * range: range
+ | Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia
+ | ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia
+ | Ands of pats: SynPat list * range: range
+ | As of lhsPat: SynPat * rhsPat: SynPat * range: range
+ | LongIdent of longDotId: SynLongIdent * extraId: Ident option * typarDecls: SynValTyparDecls option * argPats: SynArgPats * accessibility: SynAccess option * range: range
+ ...
+ member Range: range
<summary>
+ Represents a syntax tree for an F# pattern
+</summary>
+
union case SynPat.Paren: pat: SynPat * range: range -> SynPat
<summary>
+ A parenthesized pattern
+</summary>
+
val inner: SynPat
+
val functionApplication: string
+
val posOnY: pos
+
val yAndPath: (SyntaxNode * SyntaxVisitorPath) option
+
val tryNode: position: pos -> parsedInput: ParsedInput -> (SyntaxNode * SyntaxVisitorPath) option
<summary>
+ Dives to the deepest node that contains the given position,
+ returning the node and its path if found, or <c>None</c> if no
+ node contains the position.
+ </summary>
<param name="position">The position in the input file down to which to dive.</param>
<param name="parsedInput">The AST to search.</param>
<returns>The deepest node containing the given position, along with the path taken through the node's ancestors to find it.</returns>
+
val posAfterY: pos
+
val nope: (SyntaxNode * SyntaxVisitorPath) option
+
val recordExpr: string
+
val posInRecordExpr: pos
+
val recordExprRange: range option
+
val tryPick: chooser: (SyntaxVisitorPath -> SyntaxNode -> 'T option) -> position: pos -> parsedInput: ParsedInput -> 'T option
<summary>
+ Applies the given function to each node of the AST and its context (path)
+ down to a given position, returning <c>Some x</c> for the first node
+ for which the function returns <c>Some x</c> for some value <c>x</c>, otherwise <c>None</c>.
+ Traversal is short-circuited if no matching node is found through the given position.
+ </summary>
<param name="chooser">The function to apply to each node and its context to derive an optional value.</param>
<param name="position">The position in the input file down to which to apply the function.</param>
<param name="parsedInput">The AST to search.</param>
<returns>The first value for which the function returns <c>Some</c>, or <c>None</c> if no matching node is found.</returns>
<example><code lang="fsharp">
+ let range =
+ (pos, parsedInput) ||> ParsedInput.tryPick (fun _path node ->
+ match node with
+ | SyntaxNode.SynExpr (SynExpr.InterpolatedString (range = range)) when
+ rangeContainsPos range pos
+ -> Some range
+ | _ -> None)
+ </code></example>
+
union case SynExpr.Record: baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option * copyInfo: (SynExpr * BlockSeparator) option * recordFields: SynExprRecordField list * range: range -> SynExpr
<summary>
+ F# syntax: { f1=e1; ...; fn=en }
+ inherit includes location of separator (for tooling)
+ copyOpt contains range of the following WITH part (for tooling)
+ every field includes range of separator after the field (for tooling)
+</summary>
+
val rangeContainsPos: range -> pos -> bool
<summary>
+ Test to see if a range contains a position
+</summary>
+
union case Option.None: Option<'T>
+
val myFunction: string
+
val myFunctionId: string option
+
val pos0: pos
<summary>
+ The zero position
+</summary>
+
union case SynPat.LongIdent: longDotId: SynLongIdent * extraId: Ident option * typarDecls: SynValTyparDecls option * argPats: SynArgPats * accessibility: SynAccess option * range: range -> SynPat
<summary>
+ A long identifier pattern possibly with argument patterns
+</summary>
+
Multiple items
union case SynLongIdent.SynLongIdent: id: LongIdent * dotRanges: range list * trivia: FSharp.Compiler.SyntaxTrivia.IdentTrivia option list -> SynLongIdent
--------------------
type SynLongIdent =
+ | SynLongIdent of id: LongIdent * dotRanges: range list * trivia: IdentTrivia option list
+ member Dots: range list
+ member IdentsWithTrivia: SynIdent list
+ member LongIdent: LongIdent
+ member Range: range
+ member RangeWithoutAnyExtraDot: range
+ member ThereIsAnExtraDotAtTheEnd: bool
+ member Trivia: IdentTrivia list
<summary>
+ Represents a long identifier with possible '.' at end.
+
+ Typically dotRanges.Length = lid.Length-1, but they may be same if (incomplete) code ends in a dot, e.g. "Foo.Bar."
+ The dots mostly matter for parsing, and are typically ignored by the typechecker, but
+ if dotRanges.Length = lid.Length, then the parser must have reported an error, so the typechecker is allowed
+ more freedom about typechecking these expressions.
+ LongIdent can be empty list - it is used to denote that name of some AST element is absent (i.e. empty type name in inherit)
+</summary>
+
val id: x: 'T -> 'T
+
val ident: Ident
+
union case SyntaxNode.SynBinding: SynBinding -> SyntaxNode
+
property Ident.idText: string with get
+
val multipleLetsInModule: string
+
val posInLastLet: pos
+
val bodyOfLetContainingPos: SynExpr option
+
Multiple items
union case SynBinding.SynBinding: accessibility: SynAccess option * kind: SynBindingKind * isInline: bool * isMutable: bool * attributes: SynAttributes * xmlDoc: FSharp.Compiler.Xml.PreXmlDoc * valData: SynValData * headPat: SynPat * returnInfo: SynBindingReturnInfo option * expr: SynExpr * range: range * debugPoint: DebugPointAtBinding * trivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia -> SynBinding
--------------------
type SynBinding =
+ | SynBinding of accessibility: SynAccess option * kind: SynBindingKind * isInline: bool * isMutable: bool * attributes: SynAttributes * xmlDoc: PreXmlDoc * valData: SynValData * headPat: SynPat * returnInfo: SynBindingReturnInfo option * expr: SynExpr * range: range * debugPoint: DebugPointAtBinding * trivia: SynBindingTrivia
+ member RangeOfBindingWithRhs: range
+ member RangeOfBindingWithoutRhs: range
+ member RangeOfHeadPattern: range
<summary>
+ Represents a binding for a 'let' or 'member' declaration
+</summary>
+
val e: SynExpr
+
val nestedModules: string
+
val posInsideOfInnermostNestedModule: pos
+
val outermostNestedModule: string list option
+
union case SyntaxNode.SynModule: SynModuleDecl -> SyntaxNode
+
type SynModuleDecl =
+ | ModuleAbbrev of ident: Ident * longId: LongIdent * range: range
+ | NestedModule of moduleInfo: SynComponentInfo * isRecursive: bool * decls: SynModuleDecl list * isContinuing: bool * range: range * trivia: SynModuleDeclNestedModuleTrivia
+ | Let of isRecursive: bool * bindings: SynBinding list * range: range
+ | Expr of expr: SynExpr * range: range
+ | Types of typeDefns: SynTypeDefn list * range: range
+ | Exception of exnDefn: SynExceptionDefn * range: range
+ | Open of target: SynOpenDeclTarget * range: range
+ | Attributes of attributes: SynAttributes * range: range
+ | HashDirective of hashDirective: ParsedHashDirective * range: range
+ | NamespaceFragment of fragment: SynModuleOrNamespace
+ member Range: range
<summary>
+ Represents a definition within a module
+</summary>
+
union case SynModuleDecl.NestedModule: moduleInfo: SynComponentInfo * isRecursive: bool * decls: SynModuleDecl list * isContinuing: bool * range: range * trivia: FSharp.Compiler.SyntaxTrivia.SynModuleDeclNestedModuleTrivia -> SynModuleDecl
<summary>
+ A nested module definition 'module X = ...'
+</summary>
+
Multiple items
union case SynComponentInfo.SynComponentInfo: attributes: SynAttributes * typeParams: SynTyparDecls option * constraints: SynTypeConstraint list * longId: LongIdent * xmlDoc: FSharp.Compiler.Xml.PreXmlDoc * preferPostfix: bool * accessibility: SynAccess option * range: range -> SynComponentInfo
--------------------
type SynComponentInfo =
+ | SynComponentInfo of attributes: SynAttributes * typeParams: SynTyparDecls option * constraints: SynTypeConstraint list * longId: LongIdent * xmlDoc: PreXmlDoc * preferPostfix: bool * accessibility: SynAccess option * range: range
+ member Range: range
<summary>
+ Represents the syntax tree associated with the name of a type definition or module
+ in signature or implementation.
+
+ This includes the name, attributes, type parameters, constraints, documentation and accessibility
+ for a type definition or module. For modules, entries such as the type parameters are
+ always empty.
+</summary>
+
val longId: LongIdent
+
val innermostNestedModule: string list option
+
val tryPickLast: chooser: (SyntaxVisitorPath -> SyntaxNode -> 'T option) -> position: pos -> parsedInput: ParsedInput -> 'T option
<summary>
+ Applies the given function to each node of the AST and its context (path)
+ down to a given position, returning <c>Some x</c> for the last (deepest) node
+ for which the function returns <c>Some x</c> for some value <c>x</c>, otherwise <c>None</c>.
+ Traversal is short-circuited if no matching node is found through the given position.
+ </summary>
<param name="chooser">The function to apply to each node and its context to derive an optional value.</param>
<param name="position">The position in the input file down to which to apply the function.</param>
<param name="parsedInput">The AST to search.</param>
<returns>The last (deepest) value for which the function returns <c>Some</c>, or <c>None</c> if no matching node is found.</returns>
<example><code lang="fsharp">
+ let range =
+ (pos, parsedInput)
+ ||> ParsedInput.tryPickLast (fun path node ->
+ match node, path with
+ | FuncIdent range -> Some range
+ | _ -> None)
+ </code></example>
+
val nextToInnermostNestedModule: string list option
+
val visitor: SyntaxVisitorBase<string>
+
Multiple items
type SyntaxVisitorBase<'T> =
+ new: unit -> SyntaxVisitorBase<'T>
+ abstract VisitAttributeApplication: path: SyntaxVisitorPath * attributes: SynAttributeList -> 'T option + 1 overload
+ abstract VisitBinding: path: SyntaxVisitorPath * defaultTraverse: (SynBinding -> 'T option) * synBinding: SynBinding -> 'T option + 1 overload
+ abstract VisitComponentInfo: path: SyntaxVisitorPath * synComponentInfo: SynComponentInfo -> 'T option + 1 overload
+ abstract VisitEnumDefn: path: SyntaxVisitorPath * cases: SynEnumCase list * range -> 'T option + 1 overload
+ abstract VisitExpr: path: SyntaxVisitorPath * traverseSynExpr: (SynExpr -> 'T option) * defaultTraverse: (SynExpr -> 'T option) * synExpr: SynExpr -> 'T option + 1 overload
+ abstract VisitHashDirective: path: SyntaxVisitorPath * hashDirective: ParsedHashDirective * range: range -> 'T option + 1 overload
+ abstract VisitImplicitInherit: path: SyntaxVisitorPath * defaultTraverse: (SynExpr -> 'T option) * inheritedType: SynType * synArgs: SynExpr * range: range -> 'T option + 1 overload
+ abstract VisitInheritSynMemberDefn: path: SyntaxVisitorPath * componentInfo: SynComponentInfo * typeDefnKind: SynTypeDefnKind * synType: SynType * members: SynMemberDefns * range: range -> 'T option + 1 overload
+ abstract VisitInterfaceSynMemberDefnType: path: SyntaxVisitorPath * synType: SynType -> 'T option + 1 overload
+ ...
--------------------
new: unit -> SyntaxVisitorBase<'T>
+
val this: SyntaxVisitorBase<string>
+
override SyntaxVisitorBase.VisitPat: path: SyntaxVisitorPath * defaultTraverse: (SynPat -> 'T option) * synPat: SynPat -> 'T option
+
val defaultTraverse: (SynPat -> string option)
+
val synPat: SynPat
+
val result: string option
+
module SyntaxTraversal
+
+from FSharp.Compiler.Syntax
+
val Traverse: pos: pos * parseTree: ParsedInput * visitor: SyntaxVisitorBase<'T> -> 'T option
+
val secondCodeSample: string
+
val secondVisitor: SyntaxVisitorBase<SynExpr>
+
val this: SyntaxVisitorBase<SynExpr>
+
override SyntaxVisitorBase.VisitBinding: path: SyntaxVisitorPath * defaultTraverse: (SynBinding -> 'T option) * synBinding: SynBinding -> 'T option
+
val defaultTraverse: (SynBinding -> SynExpr option)
+
val binding: SynBinding
+
val cursorPos: pos
+
val secondResult: SynExpr option
+
val thirdCodeSample: string
+
val thirdCursorPos: pos
+
val thirdVisitor: SyntaxVisitorBase<int>
+
val this: SyntaxVisitorBase<int>
+
override SyntaxVisitorBase.VisitExpr: path: SyntaxVisitorPath * traverseSynExpr: (SynExpr -> 'T option) * defaultTraverse: (SynExpr -> 'T option) * synExpr: SynExpr -> 'T option
+
val traverseSynExpr: (SynExpr -> int option)
+
val defaultTraverse: (SynExpr -> int option)
+
val synExpr: SynExpr
+
union case SynExpr.Const: constant: SynConst * range: range -> SynExpr
<summary>
+ F# syntax: 1, 1.3, () etc.
+</summary>
+
type SynConst =
+ | Unit
+ | Bool of bool
+ | SByte of sbyte
+ | Byte of byte
+ | Int16 of int16
+ | UInt16 of uint16
+ | Int32 of int32
+ | UInt32 of uint32
+ | Int64 of int64
+ | UInt64 of uint64
+ ...
+ member Range: dflt: range -> range
<summary>
+ The unchecked abstract syntax tree of constants in F# types and expressions.
+</summary>
+
union case SynConst.Int32: int32 -> SynConst
<summary>
+ F# syntax: 13, 0x4000, 0o0777
+</summary>
+
val v: int32
+
val otherExpr: SynExpr
+
val thirdResult: int option
+
+
+