Movatterモバイル変換


[0]ホーム

URL:


Header menu logoF# Compiler Guide

Compiler Services: APIs for the untyped AST

The ParsedInput module

As established inTutorial: Expressions, the AST held in aParsedInput valuecan 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 theParsedInput moduleexposes a number of functions to make common operations easier.

For example:

SyntaxVisitorBase & SyntaxTraversal.Traverse

While theParsedInput module functions are usually the simplest way to meet most needs,there is also aSyntaxVisitorBase-based API that canprovide somewhat more fine-grained control over syntax traversal for a subset of use-cases at the expense of a bit moreceremony and complexity.

Examples

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"openFSharp.Compiler.CodeAnalysisopenFSharp.Compiler.TextopenFSharp.Compiler.Syntaxletchecker=FSharpChecker.Create()/// A helper for constructing a `ParsedInput` from a code snippet.letmkTreecodeSample=letparseFileResults=checker.ParseFile("FileName.fs",SourceText.ofStringcodeSample,{FSharpParsingOptions.DefaultwithSourceFiles=[|"FileName.fs"|]})|>Async.RunSynchronouslyparseFileResults.ParseTree

ParsedInput.exists

Now consider the following code sample:

letbrokenTypeDefn="""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 usingParsedInput.exists and passing in the position of the user's cursor:

// type T { A: int; B: int }// ···········↑letposInMiddleOfTypeDefn=Position.mkPos512

Given that cursor position, all we need to do is find aSynTypeDefn node:

letisPosInTypeDefn=// true.(posInMiddleOfTypeDefn,mkTreebrokenTypeDefn)||>ParsedInput.exists(fun_pathnode->matchnodewith|SyntaxNode.SynTypeDefn_->true|_->false)

If the position passed intoParsedInput.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 aboveand/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 }// ··························↑letposAfterTypeDefn=Position.mkPos528

Our function still returnstrue if the cursor is past the end of the type definition node itself:

letisPosInTypeDefn'=// Still true.(posAfterTypeDefn,mkTreebrokenTypeDefn)||>ParsedInput.exists(fun_pathnode->matchnodewith|SyntaxNode.SynTypeDefn_->true|_->false)

ParsedInput.fold

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:

letunnecessaryParentheses="""let (x) = (id (3))"""

We can gather the ranges of all unnecessary parentheses like this:

openSystem.Collections.GenericmoduleHashSet=letadditem(set:HashSet<_>)=ignore(set.Additem)setletunnecessaryParenthesesRanges=(HashSetRange.comparer,mkTreeunnecessaryParentheses)||>ParsedInput.fold(funrangespathnode->matchnodewith|SyntaxNode.SynExpr(SynExpr.Paren(expr=inner;rightParenRange=Some_;range=range))whennot(SynExpr.shouldBeParenthesizedInContextgetLineStrpathinner)->ranges|>HashSet.addrange|SyntaxNode.SynPat(SynPat.Paren(inner,range))whennot(SynPat.shouldBeParenthesizedInContextpathinner)->ranges|>HashSet.addrange|_->ranges)

ParsedInput.tryNode

Sometimes, we might just want to get whatever node is directly at a given position—for example, if the user'scursor is on an argument of a function being applied, we can find the node representing the argument and use its pathto backtrack and find the function's name.

letfunctionApplication="""f x y"""

If we have our cursor ony:

// f x y// ·····↑letposOnY=Position.mkPos25

The syntax node representing the functionf technically contains the cursor's position,butParsedInput.tryNode will keep diving until it finds thedeepest node containing the position.

We can thus get the node representingy and its ancestors (thepath) like this:

letyAndPath=// Some (SynExpr (Ident y), [SynExpr (App …); …])mkTreefunctionApplication|>ParsedInput.tryNodeposOnY

Note that, unlikeParsedInput.exists,ParsedInput.tryPick, andParsedInput.tryPickLast,ParsedInput.tryNode doesnot fall back to the nearest branch above or to the left.

// f x y// ······↑letposAfterY=Position.mkPos28

If we take the same code snippet but pass in a position aftery,we get no node:

letnope=// None.mkTreefunctionApplication|>ParsedInput.tryNodeposAfterY

ParsedInput.tryPick

Now imagine that we have a code fix for converting a record construction expression into an anonymous record constructionexpression when there is no record type in scope whose fields match.

letrecordExpr="""let r = { A = 1; B = 2 }"""

We can offer this fix when the user's cursor is inside of a record expression byusingParsedInput.tryPick to return the surrounding record expression's range, if any.

// let r = { A = 1; B = 2 }// ······················↑letposInRecordExpr=Position.mkPos225

Here, even thoughParsedInput.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, likeParsedInput.exists,ParsedInput.tryPick will also fall back to the nearest branch above and/orto the left if no node actually contains the position. In this case, we don't want to offer the code fixif the user's cursor isn't actually inside of the record expression.

letrecordExprRange=// Some (2,8--2,24).(posInRecordExpr,mkTreerecordExpr)||>ParsedInput.tryPick(fun_pathnode->matchnodewith|SyntaxNode.SynExpr(SynExpr.Record(range=range))whenRange.rangeContainsPosrangeposInRecordExpr->Somerange|_->None)

We might also sometimes want to make use of thepath parameter. Take this simple function definition:

letmyFunction="""module Liblet myFunction paramOne paramTwo =    ()"""

Imagine we want to grab themyFunction name from theheadPat in theSynBinding.

We can write a function to match the node we're looking for—andnot match anything we'renot looking for (like the argument patterns)—by taking its path into account:

letmyFunctionId=// Some "myFunction".(Position.pos0,mkTreemyFunction)||>ParsedInput.tryPick(funpathnode->// 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.matchnode,pathwith|SyntaxNode.SynPat(SynPat.LongIdent(longDotId=SynLongIdent(id=[ident]))),SyntaxNode.SynBinding_::_->// We have found what we're looking for.Someident.idText|_->// If the node or its context don't match,// we continue.None)

Instead of traversing manually fromParsedInput toSynModuleOrNamespace toSynModuleDecl.Let toSynBinding toSynPat, we leverage the default navigation that happens inParsedInput.tryPick.
ParsedInput.tryPick will short-circuit once we have indicated that we have found what we're looking for by returningSome 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:

letmultipleLetsInModule="""module Xlet a = 0let b = 1let c = 2"""

In this case, we know the user's cursor inside an IDE is placed afterc, and we are interested in the body expression of thelast let-binding.

// …// let c = 2// ·····↑letposInLastLet=Position.mkPos65

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.

letbodyOfLetContainingPos=// Some (Const (Int32 2, (6,8--6,9))).(posInLastLet,mkTreemultipleLetsInModule)||>ParsedInput.tryPick(fun_pathnode->matchnodewith|SyntaxNode.SynBinding(SynBinding(expr=e))->Somee|_->None)

As noted above,ParsedInput.tryPick will short-circuit at the first matching node.ParsedInput.tryPickLast can be used to get thelast matching node that contains a given position.

Take this example of multiple nested modules:

letnestedModules="""module Mmodule N =    module O =        module P = begin end"""

By usingParsedInput.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 moduleP, which is nested inside of moduleO, which is nested inside of moduleN,which is nested inside of top-level moduleM:

// module M//// module N =//     module O =//         module P = begin end// ···························↑letposInsideOfInnermostNestedModule=Position.mkPos628

ParsedInput.tryPick short-circuits on the first match, and since moduleN is the firstnested module whose range contains position (6, 28), that's the result we get.

letoutermostNestedModule=// Some ["N"].(posInsideOfInnermostNestedModule,mkTreenestedModules)||>ParsedInput.tryPick(fun_pathnode->matchnodewith|SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo=SynComponentInfo(longId=longId)))->Some[foridentinlongId->ident.idText]|_->None)

ParsedInput.tryPickLast

If however we use the same code snippet and pass the same position intoParsedInput.tryPickLast,we can get the name of thelast (deepest or innermost) matching node:

letinnermostNestedModule=// Some ["P"].(posInsideOfInnermostNestedModule,mkTreenestedModules)||>ParsedInput.tryPickLast(fun_pathnode->matchnodewith|SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo=SynComponentInfo(longId=longId)))->Some[foridentinlongId->ident.idText]|_->None)

If we want the next-to-innermost nested module, we can do likewise but make use of thepath parameter:

letnextToInnermostNestedModule=// Some ["O"].(posInsideOfInnermostNestedModule,mkTreenestedModules)||>ParsedInput.tryPickLast(funpathnode->matchnode,pathwith|SyntaxNode.SynModule(SynModuleDecl.NestedModule_),SyntaxNode.SynModule(SynModuleDecl.NestedModule(moduleInfo=SynComponentInfo(longId=longId)))::_->Some[foridentinlongId->ident.idText]|_->None)

SyntaxTraversal.Traverse

Consider again the following code sample:

letcodeSample="""module Liblet myFunction paramOne paramTwo =    ()"""

Imagine we wish to grab themyFunction name from theheadPat in theSynBinding.

We can create a visitor to traverse the tree and find the function name:

letvisitor={newSyntaxVisitorBase<string>()withoverridethis.VisitPat(path,defaultTraverse,synPat)=// First check if the pattern is what we are looking for.matchsynPatwith|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.matchpathwith// 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.Someident.idText// If the parent is something else, we can skip it here.|_->None|_->None}letresult=SyntaxTraversal.Traverse(Position.pos0,mkTreecodeSample,visitor)// Some "myFunction"

Instead of traversing manually fromParsedInput toSynModuleOrNamespace toSynModuleDecl.Let toSynBinding toSynPat, we leverage the default navigation that happens inSyntaxTraversal.Traverse.
ASyntaxVisitorBase will shortcut all other code paths once a singleVisitXYZ 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.

SyntaxTraversal.Traverse: using position

Let's now consider a second example where we know the user's cursor inside an IDE is placed afterc and we are interested in the body expression of the let binding.

letsecondCodeSample="""module Xlet a = 0let b = 1let c = 2"""letsecondVisitor={newSyntaxVisitorBase<SynExpr>()withoverridethis.VisitBinding(path,defaultTraverse,binding)=matchbindingwith|SynBinding(expr=e)->Somee}letcursorPos=Position.mkPos65letsecondResult=SyntaxTraversal.Traverse(cursorPos,mkTreesecondCodeSample,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.

SyntaxTraversal.Traverse: using defaultTraverse

Lastly, someVisitXYZ 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.Consider1 + 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 of4 using the following visitor:

letthirdCodeSample="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) })*)letthirdCursorPos=Position.mkPos122letthirdVisitor={newSyntaxVisitorBase<int>()withoverridethis.VisitExpr(path,traverseSynExpr,defaultTraverse,synExpr)=matchsynExprwith|SynExpr.Const(constant=SynConst.Int32v)->Somev// We do want to continue to traverse when nodes like `SynExpr.App` are found.|otherExpr->defaultTraverseotherExpr}letthirdResult=SyntaxTraversal.Traverse(cursorPos,mkTreethirdCodeSample,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 passPosition.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 * exn option> 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.")>] ?useTransparentCompiler: bool * [<Experimental ("This parameter is experimental and likely to be removed in the future.")>] ?transparentCompilerCacheSizes: TransparentCompiler.CacheSizes -> 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 SourceTextfrom 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 with get
<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 * objnull -> 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 * objnull -> 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 Positionfrom FSharp.Compiler.Text

--------------------
[<Struct>]type Position = member Column: int with get member Line: int with get
<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 ParsedInputfrom 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 with get member Identifiers: Set<string> with get member QualifiedName: QualifiedNameOfFile with get member Range: range with get
<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) ||&gt; ParsedInput.exists (fun _path node -&gt; match node with | SyntaxNode.SynTypeDefn _ -&gt; true | _ -&gt; false) </code></example>
val _path: SyntaxVisitorPath
val node: SyntaxNode
Multiple items
module SyntaxNodefrom 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 with get
<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
val getLineStr: line: int -> string
val line: int
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 failwith: message: string -> 'T
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 Rangefrom FSharp.Compiler.Text

--------------------
[<Struct>]type Range = member End: pos with get member EndColumn: int with get member EndLine: int with get member EndRange: range with get member FileName: string with get member IsSynthetic: bool with get member Start: pos with get member StartColumn: int with get member StartLine: int with get member StartRange: range with get
<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) ||&gt; ParsedInput.fold (fun acc path node -&gt; match node with | SyntaxNode.SynExpr (SynExpr.Paren (expr = inner; rightParenRange = Some _; range = range)) when not (SynExpr.shouldBeParenthesizedInContext getLineString path inner) -&gt; ignore (acc.Add range) acc | SyntaxNode.SynPat (SynPat.Paren (inner, range)) when not (SynPat.shouldBeParenthesizedInContext path inner) -&gt; ignore (acc.Add range) acc | _ -&gt; acc) </code></example>
val ranges: HashSet<range>
val path: SyntaxVisitorPath
union case SyntaxNode.SynExpr: SynExpr -> SyntaxNode
Multiple items
module SynExprfrom FSharp.Compiler.Syntax

--------------------
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 with get member Range: range with get member RangeOfFirstPortion: range with get member RangeWithoutAnyExtraDot: range with get
<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>
val shouldBeParenthesizedInContext: getSourceLineStr: (int -> string) -> path: SyntaxVisitorPath -> expr: SynExpr -> bool
<summary> Returns true if the given expression should be parenthesized in the given context, otherwise false. </summary>
<param name="getSourceLineStr">A function for getting the text of a given source line.</param>
<param name="path">The expression's ancestor nodes.</param>
<param name="expr">The expression to check.</param>
<returns>True if the given expression should be parenthesized in the given context, otherwise false.</returns>
union case SyntaxNode.SynPat: SynPat -> SyntaxNode
Multiple items
module SynPatfrom FSharp.Compiler.Syntax

--------------------
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 with get
<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 shouldBeParenthesizedInContext: path: SyntaxVisitorPath -> pat: SynPat -> bool
<summary> Returns true if the given pattern should be parenthesized in the given context, otherwise false. </summary>
<param name="path">The pattern's ancestor nodes.</param>
<param name="pat">The pattern to check.</param>
<returns>True if the given pattern should be parenthesized in the given context, otherwise false.</returns>
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) ||&gt; ParsedInput.tryPick (fun _path node -&gt; match node with | SyntaxNode.SynExpr (SynExpr.InterpolatedString (range = range)) when rangeContainsPos range pos -&gt; Some range | _ -&gt; 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 with get member IdentsWithTrivia: SynIdent list with get member LongIdent: LongIdent with get member Range: range with get member RangeWithoutAnyExtraDot: range with get member ThereIsAnExtraDotAtTheEnd: bool with get member Trivia: IdentTrivia list with get
<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 with get member RangeOfBindingWithoutRhs: range with get member RangeOfHeadPattern: range with get
<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 with get
<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 with get
<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) ||&gt; ParsedInput.tryPickLast (fun path node -&gt; match node, path with | FuncIdent range -&gt; Some range | _ -&gt; 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 SyntaxTraversalfrom 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

On this page

Type something to start searching.


[8]ページ先頭

©2009-2025 Movatter.jp