未验证 提交 db4bf11c 编写于 作者: D Don Syme 提交者: GitHub

Format src/Compiler/SyntaxTree (#13237)

* adjust settings

* adjust file

* adjust settings

* adjust code

* apply formatting
上级 1632f460
......@@ -22,10 +22,13 @@ src/Compiler/Legacy/**/*.fs
src/Compiler/Optimize/**/*.fs
src/Compiler/Service/**/*.fs
src/Compiler/Symbols/**/*.fs
src/Compiler/SyntaxTree/**/*.fs
src/Compiler/TypedTree/**/*.fs
src/Microsoft.FSharp.Compiler/**/*.fs
# Explicitly unformatted file that needs more care to get it to format well
src/Compiler/SyntaxTree/LexFilter.fs
# Fantomas limitations on implementation files in FSharp.Core (to investigate)
src/FSharp.Core/array2.fs
......
......@@ -22,24 +22,31 @@ open FSharp.Compiler.Text.Range
/// The "mock" file name used by fsi.exe when reading from stdin.
/// Has special treatment by the lexer, i.e. __SOURCE_DIRECTORY__ becomes GetCurrentDirectory()
let stdinMockFileName = "stdin"
let stdinMockFileName = "stdin"
/// Lexer args: status of #light processing. Mutated when a #light
/// directive is processed. This alters the behaviour of the lexfilter.
[<Sealed>]
type IndentationAwareSyntaxStatus(initial:bool,warn:bool) =
type IndentationAwareSyntaxStatus(initial: bool, warn: bool) =
let mutable status = None
member x.Status
with get() = match status with None -> initial | Some v -> v
and set v = status <- Some(v)
member x.Status
with get () =
match status with
| None -> initial
| Some v -> v
and set v = status <- Some(v)
member x.ExplicitlySet = status.IsSome
member x.WarnOnMultipleTokens = warn
/// Manage lexer resources (string interning)
[<Sealed>]
type LexResourceManager(?capacity: int) =
let strings = System.Collections.Concurrent.ConcurrentDictionary<string, token>(Environment.ProcessorCount, defaultArg capacity 1024)
member x.InternIdentifierToken(s) =
let strings =
System.Collections.Concurrent.ConcurrentDictionary<string, token>(Environment.ProcessorCount, defaultArg capacity 1024)
member x.InternIdentifierToken(s) =
match strings.TryGetValue s with
| true, res -> res
| _ ->
......@@ -47,17 +54,17 @@ type LexResourceManager(?capacity: int) =
strings[s] <- res
res
/// Lexer parameters
type LexArgs =
/// Lexer parameters
type LexArgs =
{
conditionalDefines: string list
resourceManager: LexResourceManager
diagnosticsLogger: DiagnosticsLogger
applyLineDirectives: bool
pathMap: PathMap
mutable ifdefStack: LexerIfdefStack
mutable indentationSyntaxStatus : IndentationAwareSyntaxStatus
mutable stringNest: LexerInterpolatedStringNesting
conditionalDefines: string list
resourceManager: LexResourceManager
diagnosticsLogger: DiagnosticsLogger
applyLineDirectives: bool
pathMap: PathMap
mutable ifdefStack: LexerIfdefStack
mutable indentationSyntaxStatus: IndentationAwareSyntaxStatus
mutable stringNest: LexerInterpolatedStringNesting
}
/// possible results of lexing a long Unicode escape sequence in a string literal, e.g. "\U0001F47D",
......@@ -68,33 +75,41 @@ type LongUnicodeLexResult =
| Invalid
let mkLexargs (conditionalDefines, indentationSyntaxStatus, resourceManager, ifdefStack, diagnosticsLogger, pathMap: PathMap) =
{
conditionalDefines = conditionalDefines
ifdefStack = ifdefStack
indentationSyntaxStatus = indentationSyntaxStatus
resourceManager = resourceManager
diagnosticsLogger = diagnosticsLogger
applyLineDirectives = true
stringNest = []
pathMap = pathMap
{
conditionalDefines = conditionalDefines
ifdefStack = ifdefStack
indentationSyntaxStatus = indentationSyntaxStatus
resourceManager = resourceManager
diagnosticsLogger = diagnosticsLogger
applyLineDirectives = true
stringNest = []
pathMap = pathMap
}
/// Register the lexbuf and call the given function
let reusingLexbufForParsing lexbuf f =
let reusingLexbufForParsing lexbuf f =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
LexbufLocalXmlDocStore.ClearXmlDoc lexbuf
LexbufCommentStore.ClearComments lexbuf
try
f ()
f ()
with e ->
raise (WrappedError(e, (try lexbuf.LexemeRange with _ -> range0)))
let resetLexbufPos fileName (lexbuf: Lexbuf) =
lexbuf.EndPos <- Position.FirstLine (FileIndex.fileIndexOfFile fileName)
raise (
WrappedError(
e,
(try
lexbuf.LexemeRange
with _ ->
range0)
)
)
let resetLexbufPos fileName (lexbuf: Lexbuf) =
lexbuf.EndPos <- Position.FirstLine(FileIndex.fileIndexOfFile fileName)
/// Reset the lexbuf, configure the initial position with the given file name and call the given function
let usingLexbufForParsing (lexbuf:Lexbuf, fileName) f =
let usingLexbufForParsing (lexbuf: Lexbuf, fileName) f =
resetLexbufPos fileName lexbuf
reusingLexbufForParsing lexbuf (fun () -> f lexbuf)
......@@ -104,26 +119,31 @@ let usingLexbufForParsing (lexbuf:Lexbuf, fileName) f =
let stringBufferAsString (buf: ByteBuffer) =
let buf = buf.AsMemory()
if buf.Length % 2 <> 0 then failwith "Expected even number of bytes"
let chars : char[] = Array.zeroCreate (buf.Length/2)
for i = 0 to (buf.Length/2) - 1 do
let hi = buf.Span[i*2+1]
let lo = buf.Span[i*2]
if buf.Length % 2 <> 0 then
failwith "Expected even number of bytes"
let chars: char[] = Array.zeroCreate (buf.Length / 2)
for i = 0 to (buf.Length / 2) - 1 do
let hi = buf.Span[i * 2 + 1]
let lo = buf.Span[i * 2]
let c = char (((int hi) * 256) + (int lo))
chars[i] <- c
String(chars)
/// When lexing bytearrays we don't expect to see any unicode stuff.
/// Likewise when lexing string constants we shouldn't see any trigraphs > 127
/// So to turn the bytes collected in the string buffer back into a bytearray
/// we just take every second byte we stored. Note all bytes > 127 should have been
/// stored using addIntChar
let stringBufferAsBytes (buf: ByteBuffer) =
/// When lexing bytearrays we don't expect to see any unicode stuff.
/// Likewise when lexing string constants we shouldn't see any trigraphs > 127
/// So to turn the bytes collected in the string buffer back into a bytearray
/// we just take every second byte we stored. Note all bytes > 127 should have been
/// stored using addIntChar
let stringBufferAsBytes (buf: ByteBuffer) =
let bytes = buf.AsMemory()
Array.init (bytes.Length / 2) (fun i -> bytes.Span[i*2])
Array.init (bytes.Length / 2) (fun i -> bytes.Span[i * 2])
[<Flags>]
type LexerStringFinisherContext =
type LexerStringFinisherContext =
| InterpolatedPart = 1
| Verbatim = 2
| TripleQuote = 4
......@@ -132,113 +152,122 @@ type LexerStringFinisher =
| LexerStringFinisher of (ByteBuffer -> LexerStringKind -> LexerStringFinisherContext -> LexerContinuation -> token)
member fin.Finish (buf: ByteBuffer) kind context cont =
let (LexerStringFinisher f) = fin
let (LexerStringFinisher f) = fin
f buf kind context cont
static member Default =
LexerStringFinisher (fun buf kind context cont ->
LexerStringFinisher(fun buf kind context cont ->
let isPart = context.HasFlag(LexerStringFinisherContext.InterpolatedPart)
let isVerbatim = context.HasFlag(LexerStringFinisherContext.Verbatim)
let isTripleQuote = context.HasFlag(LexerStringFinisherContext.TripleQuote)
if kind.IsInterpolated then
if kind.IsInterpolated then
let s = stringBufferAsString buf
if kind.IsInterpolatedFirst then
let synStringKind =
if isTripleQuote then
SynStringKind.TripleQuote
elif isVerbatim then
SynStringKind.Verbatim
else
SynStringKind.Regular
if isPart then
INTERP_STRING_BEGIN_PART (s, synStringKind, cont)
else
INTERP_STRING_BEGIN_END (s, synStringKind, cont)
else
if isTripleQuote then SynStringKind.TripleQuote
elif isVerbatim then SynStringKind.Verbatim
else SynStringKind.Regular
if isPart then
INTERP_STRING_PART (s, cont)
INTERP_STRING_BEGIN_PART(s, synStringKind, cont)
else
INTERP_STRING_END (s, cont)
INTERP_STRING_BEGIN_END(s, synStringKind, cont)
else if isPart then
INTERP_STRING_PART(s, cont)
else
INTERP_STRING_END(s, cont)
elif kind.IsByteString then
let synByteStringKind = if isVerbatim then SynByteStringKind.Verbatim else SynByteStringKind.Regular
BYTEARRAY (stringBufferAsBytes buf, synByteStringKind, cont)
else
let synStringKind =
let synByteStringKind =
if isVerbatim then
SynStringKind.Verbatim
elif isTripleQuote then
SynStringKind.TripleQuote
SynByteStringKind.Verbatim
else
SynStringKind.Regular
STRING (stringBufferAsString buf, synStringKind, cont)
)
SynByteStringKind.Regular
let addUnicodeString (buf: ByteBuffer) (x:string) =
buf.EmitBytes (Encoding.Unicode.GetBytes x)
BYTEARRAY(stringBufferAsBytes buf, synByteStringKind, cont)
else
let synStringKind =
if isVerbatim then SynStringKind.Verbatim
elif isTripleQuote then SynStringKind.TripleQuote
else SynStringKind.Regular
STRING(stringBufferAsString buf, synStringKind, cont))
let addUnicodeString (buf: ByteBuffer) (x: string) =
buf.EmitBytes(Encoding.Unicode.GetBytes x)
let addIntChar (buf: ByteBuffer) c =
buf.EmitIntAsByte (c % 256)
buf.EmitIntAsByte (c / 256)
let addIntChar (buf: ByteBuffer) c =
buf.EmitIntAsByte(c % 256)
buf.EmitIntAsByte(c / 256)
let addUnicodeChar buf c = addIntChar buf (int c)
let addByteChar buf (c:char) = addIntChar buf (int32 c % 256)
let addByteChar buf (c: char) = addIntChar buf (int32 c % 256)
/// Sanity check that high bytes are zeros. Further check each low byte <= 127
let stringBufferIsBytes (buf: ByteBuffer) =
/// Sanity check that high bytes are zeros. Further check each low byte <= 127
let stringBufferIsBytes (buf: ByteBuffer) =
let bytes = buf.AsMemory()
let mutable ok = true
for i = 0 to bytes.Length / 2-1 do
if bytes.Span[i*2+1] <> 0uy then ok <- false
let mutable ok = true
for i = 0 to bytes.Length / 2 - 1 do
if bytes.Span[i * 2 + 1] <> 0uy then ok <- false
ok
let newline (lexbuf:LexBuffer<_>) =
lexbuf.EndPos <- lexbuf.EndPos.NextLine
let newline (lexbuf: LexBuffer<_>) = lexbuf.EndPos <- lexbuf.EndPos.NextLine
let advanceColumnBy (lexbuf:LexBuffer<_>) n =
let advanceColumnBy (lexbuf: LexBuffer<_>) n =
lexbuf.EndPos <- lexbuf.EndPos.ShiftColumnBy(n)
let trigraph c1 c2 c3 =
let digit (c:char) = int c - int '0'
let digit (c: char) = int c - int '0'
char (digit c1 * 100 + digit c2 * 10 + digit c3)
let digit d =
if d >= '0' && d <= '9' then int32 d - int32 '0'
else failwith "digit"
let digit d =
if d >= '0' && d <= '9' then
int32 d - int32 '0'
else
failwith "digit"
let hexdigit d =
if d >= '0' && d <= '9' then digit d
let hexdigit d =
if d >= '0' && d <= '9' then digit d
elif d >= 'a' && d <= 'f' then int32 d - int32 'a' + 10
elif d >= 'A' && d <= 'F' then int32 d - int32 'A' + 10
else failwith "hexdigit"
else failwith "hexdigit"
let unicodeGraphShort (s:string) =
let unicodeGraphShort (s: string) =
if s.Length <> 4 then failwith "unicodegraph"
uint16 (hexdigit s[0] * 4096 + hexdigit s[1] * 256 + hexdigit s[2] * 16 + hexdigit s[3])
let hexGraphShort (s:string) =
let hexGraphShort (s: string) =
if s.Length <> 2 then failwith "hexgraph"
uint16 (hexdigit s[0] * 16 + hexdigit s[1])
let unicodeGraphLong (s:string) =
let unicodeGraphLong (s: string) =
if s.Length <> 8 then failwith "unicodeGraphLong"
let high = hexdigit s[0] * 4096 + hexdigit s[1] * 256 + hexdigit s[2] * 16 + hexdigit s[3] in
let low = hexdigit s[4] * 4096 + hexdigit s[5] * 256 + hexdigit s[6] * 16 + hexdigit s[7] in
let high =
hexdigit s[0] * 4096 + hexdigit s[1] * 256 + hexdigit s[2] * 16 + hexdigit s[3] in
let low =
hexdigit s[4] * 4096 + hexdigit s[5] * 256 + hexdigit s[6] * 16 + hexdigit s[7] in
// not a surrogate pair
if high = 0 then SingleChar(uint16 low)
if high = 0 then
SingleChar(uint16 low)
// invalid encoding
elif high > 0x10 then Invalid
elif high > 0x10 then
Invalid
// valid supplementary character: code points U+10000 to U+10FFFF
// valid surrogate pair: see http://www.unicode.org/versions/latest/ch03.pdf , "Surrogates" section
// high-surrogate code point (U+D800 to U+DBFF) followed by low-surrogate code point (U+DC00 to U+DFFF)
else
let codepoint = high * 0x10000 + low
let hiSurr = uint16 (0xD800 + ((codepoint - 0x10000) / 0x400))
let loSurr = uint16 (0xDC00 + ((codepoint - 0x10000) % 0x400))
SurrogatePair(hiSurr, loSurr)
let codepoint = high * 0x10000 + low
let hiSurr = uint16 (0xD800 + ((codepoint - 0x10000) / 0x400))
let loSurr = uint16 (0xDC00 + ((codepoint - 0x10000) % 0x400))
SurrogatePair(hiSurr, loSurr)
let escape c =
let escape c =
match c with
| '\\' -> '\\'
| '\'' -> '\''
......@@ -253,146 +282,171 @@ let escape c =
//------------------------------------------------------------------------
// Keyword table
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
exception ReservedKeyword of string * range
module Keywords =
module Keywords =
type private compatibilityMode =
| ALWAYS (* keyword *)
| FSHARP (* keyword, but an identifier under --ml-compatibility mode *)
let private keywordList =
[ FSHARP, "abstract", ABSTRACT
ALWAYS, "and" ,AND
ALWAYS, "as" ,AS
ALWAYS, "assert" ,ASSERT
ALWAYS, "asr" ,INFIX_STAR_STAR_OP "asr"
ALWAYS, "base" ,BASE
ALWAYS, "begin" ,BEGIN
ALWAYS, "class" ,CLASS
FSHARP, "const" ,CONST
FSHARP, "default" ,DEFAULT
FSHARP, "delegate" ,DELEGATE
ALWAYS, "do" ,DO
ALWAYS, "done" ,DONE
FSHARP, "downcast" ,DOWNCAST
ALWAYS, "downto" ,DOWNTO
FSHARP, "elif" ,ELIF
ALWAYS, "else" ,ELSE
ALWAYS, "end" ,END
ALWAYS, "exception" ,EXCEPTION
FSHARP, "extern" ,EXTERN
ALWAYS, "false" ,FALSE
ALWAYS, "finally" ,FINALLY
FSHARP, "fixed" ,FIXED
ALWAYS, "for" ,FOR
ALWAYS, "fun" ,FUN
ALWAYS, "function" ,FUNCTION
FSHARP, "global" ,GLOBAL
ALWAYS, "if" ,IF
ALWAYS, "in" ,IN
ALWAYS, "inherit" ,INHERIT
FSHARP, "inline" ,INLINE
FSHARP, "interface" ,INTERFACE
FSHARP, "internal" ,INTERNAL
ALWAYS, "land" ,INFIX_STAR_DIV_MOD_OP "land"
ALWAYS, "lazy" ,LAZY
ALWAYS, "let" ,LET(false)
ALWAYS, "lor" ,INFIX_STAR_DIV_MOD_OP "lor"
ALWAYS, "lsl" ,INFIX_STAR_STAR_OP "lsl"
ALWAYS, "lsr" ,INFIX_STAR_STAR_OP "lsr"
ALWAYS, "lxor" ,INFIX_STAR_DIV_MOD_OP "lxor"
ALWAYS, "match" ,MATCH
FSHARP, "member" ,MEMBER
ALWAYS, "mod" ,INFIX_STAR_DIV_MOD_OP "mod"
ALWAYS, "module" ,MODULE
ALWAYS, "mutable" ,MUTABLE
FSHARP, "namespace" ,NAMESPACE
ALWAYS, "new" ,NEW
FSHARP, "null" ,NULL
ALWAYS, "of" ,OF
ALWAYS, "open" ,OPEN
ALWAYS, "or" ,OR
FSHARP, "override" ,OVERRIDE
ALWAYS, "private" ,PRIVATE
FSHARP, "public" ,PUBLIC
ALWAYS, "rec" ,REC
FSHARP, "return" ,YIELD(false)
ALWAYS, "sig" ,SIG
FSHARP, "static" ,STATIC
ALWAYS, "struct" ,STRUCT
ALWAYS, "then" ,THEN
ALWAYS, "to" ,TO
ALWAYS, "true" ,TRUE
ALWAYS, "try" ,TRY
ALWAYS, "type" ,TYPE
FSHARP, "upcast" ,UPCAST
FSHARP, "use" ,LET(true)
ALWAYS, "val" ,VAL
FSHARP, "void" ,VOID
ALWAYS, "when" ,WHEN
ALWAYS, "while" ,WHILE
ALWAYS, "with" ,WITH
FSHARP, "yield" ,YIELD(true)
ALWAYS, "_" ,UNDERSCORE
(*------- for prototyping and explaining offside rule *)
FSHARP, "__token_OBLOCKSEP" ,OBLOCKSEP
FSHARP, "__token_OWITH" ,OWITH
FSHARP, "__token_ODECLEND" ,ODECLEND
FSHARP, "__token_OTHEN" ,OTHEN
FSHARP, "__token_OELSE" ,OELSE
FSHARP, "__token_OEND" ,OEND
FSHARP, "__token_ODO" ,ODO
FSHARP, "__token_OLET" ,OLET(true)
FSHARP, "__token_constraint",CONSTRAINT
]
(*------- reserved keywords which are ml-compatibility ids *)
@ List.map (fun s -> (FSHARP,s,RESERVED))
[ "break"; "checked"; "component"; "constraint"; "continue"
"fori"; "include"; "mixin"
"parallel"; "params"; "process"; "protected"; "pure"
"sealed"; "trait"; "tailcall"; "virtual" ]
| ALWAYS (* keyword *)
| FSHARP (* keyword, but an identifier under --ml-compatibility mode *)
let private keywordList =
[
FSHARP, "abstract", ABSTRACT
ALWAYS, "and", AND
ALWAYS, "as", AS
ALWAYS, "assert", ASSERT
ALWAYS, "asr", INFIX_STAR_STAR_OP "asr"
ALWAYS, "base", BASE
ALWAYS, "begin", BEGIN
ALWAYS, "class", CLASS
FSHARP, "const", CONST
FSHARP, "default", DEFAULT
FSHARP, "delegate", DELEGATE
ALWAYS, "do", DO
ALWAYS, "done", DONE
FSHARP, "downcast", DOWNCAST
ALWAYS, "downto", DOWNTO
FSHARP, "elif", ELIF
ALWAYS, "else", ELSE
ALWAYS, "end", END
ALWAYS, "exception", EXCEPTION
FSHARP, "extern", EXTERN
ALWAYS, "false", FALSE
ALWAYS, "finally", FINALLY
FSHARP, "fixed", FIXED
ALWAYS, "for", FOR
ALWAYS, "fun", FUN
ALWAYS, "function", FUNCTION
FSHARP, "global", GLOBAL
ALWAYS, "if", IF
ALWAYS, "in", IN
ALWAYS, "inherit", INHERIT
FSHARP, "inline", INLINE
FSHARP, "interface", INTERFACE
FSHARP, "internal", INTERNAL
ALWAYS, "land", INFIX_STAR_DIV_MOD_OP "land"
ALWAYS, "lazy", LAZY
ALWAYS, "let", LET(false)
ALWAYS, "lor", INFIX_STAR_DIV_MOD_OP "lor"
ALWAYS, "lsl", INFIX_STAR_STAR_OP "lsl"
ALWAYS, "lsr", INFIX_STAR_STAR_OP "lsr"
ALWAYS, "lxor", INFIX_STAR_DIV_MOD_OP "lxor"
ALWAYS, "match", MATCH
FSHARP, "member", MEMBER
ALWAYS, "mod", INFIX_STAR_DIV_MOD_OP "mod"
ALWAYS, "module", MODULE
ALWAYS, "mutable", MUTABLE
FSHARP, "namespace", NAMESPACE
ALWAYS, "new", NEW
FSHARP, "null", NULL
ALWAYS, "of", OF
ALWAYS, "open", OPEN
ALWAYS, "or", OR
FSHARP, "override", OVERRIDE
ALWAYS, "private", PRIVATE
FSHARP, "public", PUBLIC
ALWAYS, "rec", REC
FSHARP, "return", YIELD(false)
ALWAYS, "sig", SIG
FSHARP, "static", STATIC
ALWAYS, "struct", STRUCT
ALWAYS, "then", THEN
ALWAYS, "to", TO
ALWAYS, "true", TRUE
ALWAYS, "try", TRY
ALWAYS, "type", TYPE
FSHARP, "upcast", UPCAST
FSHARP, "use", LET(true)
ALWAYS, "val", VAL
FSHARP, "void", VOID
ALWAYS, "when", WHEN
ALWAYS, "while", WHILE
ALWAYS, "with", WITH
FSHARP, "yield", YIELD(true)
ALWAYS, "_", UNDERSCORE
(*------- for prototyping and explaining offside rule *)
FSHARP, "__token_OBLOCKSEP", OBLOCKSEP
FSHARP, "__token_OWITH", OWITH
FSHARP, "__token_ODECLEND", ODECLEND
FSHARP, "__token_OTHEN", OTHEN
FSHARP, "__token_OELSE", OELSE
FSHARP, "__token_OEND", OEND
FSHARP, "__token_ODO", ODO
FSHARP, "__token_OLET", OLET(true)
FSHARP, "__token_constraint", CONSTRAINT
]
(*------- reserved keywords which are ml-compatibility ids *)
@ List.map
(fun s -> (FSHARP, s, RESERVED))
[
"break"
"checked"
"component"
"constraint"
"continue"
"fori"
"include"
"mixin"
"parallel"
"params"
"process"
"protected"
"pure"
"sealed"
"trait"
"tailcall"
"virtual"
]
//------------------------------------------------------------------------
// Keywords
//-----------------------------------------------------------------------
let keywordNames =
keywordList |> List.map (fun (_, w, _) -> w)
let keywordNames = keywordList |> List.map (fun (_, w, _) -> w)
let keywordTable =
let keywordTable =
let tab = System.Collections.Generic.Dictionary<string, token>(100)
for _, keyword, token in keywordList do
for _, keyword, token in keywordList do
tab.Add(keyword, token)
tab
let KeywordToken s = keywordTable[s]
let IdentifierToken args (lexbuf:Lexbuf) (s:string) =
if IsCompilerGeneratedName s then
warning(Error(FSComp.SR.lexhlpIdentifiersContainingAtSymbolReserved(), lexbuf.LexemeRange))
let IdentifierToken args (lexbuf: Lexbuf) (s: string) =
if IsCompilerGeneratedName s then
warning (Error(FSComp.SR.lexhlpIdentifiersContainingAtSymbolReserved (), lexbuf.LexemeRange))
args.resourceManager.InternIdentifierToken s
let KeywordOrIdentifierToken args (lexbuf:Lexbuf) s =
let KeywordOrIdentifierToken args (lexbuf: Lexbuf) s =
match keywordTable.TryGetValue s with
| true, v ->
match v with
match v with
| RESERVED ->
warning(ReservedKeyword(FSComp.SR.lexhlpIdentifierReserved(s), lexbuf.LexemeRange))
warning (ReservedKeyword(FSComp.SR.lexhlpIdentifierReserved (s), lexbuf.LexemeRange))
IdentifierToken args lexbuf s
| _ ->
match s with
| "land" | "lor" | "lxor"
| "lsl" | "lsr" | "asr" ->
match s with
| "land"
| "lor"
| "lxor"
| "lsl"
| "lsr"
| "asr" ->
if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then
mlCompatWarning (FSComp.SR.mlCompatKeyword(s)) lexbuf.LexemeRange
mlCompatWarning (FSComp.SR.mlCompatKeyword (s)) lexbuf.LexemeRange
| _ -> ()
v
| _ ->
match s with
match s with
| "__SOURCE_DIRECTORY__" ->
let fileName = FileIndex.fileOfFileIndex lexbuf.StartPos.FileIndex
let dirname =
if String.IsNullOrWhiteSpace(fileName) then
String.Empty
......@@ -403,13 +457,11 @@ module Keywords =
|> FileSystem.GetFullPathShim (* asserts that path is already absolute *)
|> System.IO.Path.GetDirectoryName
if String.IsNullOrEmpty dirname then dirname
else PathMap.applyDir args.pathMap dirname
if String.IsNullOrEmpty dirname then
dirname
else
PathMap.applyDir args.pathMap dirname
|> fun dir -> KEYWORD_STRING(s, dir)
| "__SOURCE_FILE__" ->
KEYWORD_STRING (s, System.IO.Path.GetFileName (FileIndex.fileOfFileIndex lexbuf.StartPos.FileIndex))
| "__LINE__" ->
KEYWORD_STRING (s, string lexbuf.StartPos.Line)
| _ ->
IdentifierToken args lexbuf s
| "__SOURCE_FILE__" -> KEYWORD_STRING(s, System.IO.Path.GetFileName(FileIndex.fileOfFileIndex lexbuf.StartPos.FileIndex))
| "__LINE__" -> KEYWORD_STRING(s, string lexbuf.StartPos.Line)
| _ -> IdentifierToken args lexbuf s
......@@ -25,30 +25,28 @@ open Internal.Utilities.Text.Parsing
/// information about the grammar at the point where the error occurred, e.g. what tokens
/// are valid to shift next at that point in the grammar. This information is processed in CompileOps.fs.
[<NoEquality; NoComparison>]
exception SyntaxError of obj (* ParseErrorContext<_> *) * range: range
exception SyntaxError of obj (* ParseErrorContext<_> *) * range: range
exception IndentationProblem of string * range
let warningStringOfCoords line column =
sprintf "(%d:%d)" line (column + 1)
let warningStringOfCoords line column = sprintf "(%d:%d)" line (column + 1)
let warningStringOfPos (p: pos) =
warningStringOfCoords p.Line p.Column
let warningStringOfPos (p: pos) = warningStringOfCoords p.Line p.Column
//------------------------------------------------------------------------
// Parsing: getting positions from the lexer
//------------------------------------------------------------------------
/// Get an F# compiler position from a lexer position
let posOfLexPosition (p: Position) =
mkPos p.Line p.Column
let posOfLexPosition (p: Position) = mkPos p.Line p.Column
/// Get an F# compiler range from a lexer range
let mkSynRange (p1: Position) (p2: Position) =
mkFileIndexRange p1.FileIndex (posOfLexPosition p1) (posOfLexPosition p2)
type LexBuffer<'Char> with
member lexbuf.LexemeRange = mkSynRange lexbuf.StartPos lexbuf.EndPos
member lexbuf.LexemeRange = mkSynRange lexbuf.StartPos lexbuf.EndPos
/// Get the range corresponding to the result of a grammar rule while it is being reduced
let lhs (parseState: IParseState) =
......@@ -71,6 +69,7 @@ type IParseState with
member x.SynArgNameGenerator =
let key = "SynArgNameGenerator"
let bls = x.LexBuffer.BufferLocalStore
let gen =
match bls.TryGetValue key with
| true, gen -> gen
......@@ -78,6 +77,7 @@ type IParseState with
let gen = box (SynArgNameGenerator())
bls[key] <- gen
gen
gen :?> SynArgNameGenerator
/// Reset the generator used for compiler-generated argument names.
......@@ -97,13 +97,13 @@ module LexbufLocalXmlDocStore =
| true, collector -> collector
| _ ->
let collector = box (XmlDocCollector())
lexbuf.BufferLocalStore[xmlDocKey] <- collector
lexbuf.BufferLocalStore[ xmlDocKey ] <- collector
collector
|> unbox<XmlDocCollector>
let ClearXmlDoc (lexbuf: Lexbuf) =
lexbuf.BufferLocalStore[xmlDocKey] <- box (XmlDocCollector())
lexbuf.BufferLocalStore[ xmlDocKey ] <- box (XmlDocCollector())
/// Called from the lexer to save a single line of XML doc comment.
let SaveXmlDocLine (lexbuf: Lexbuf, lineText, range: range) =
......@@ -132,13 +132,12 @@ module LexbufLocalXmlDocStore =
/// Called from the parser each time we parse a construct that marks the end of an XML doc comment range,
/// e.g. a 'type' declaration. The markerRange is the range of the keyword that delimits the construct.
let GrabXmlDocBeforeMarker (lexbuf: Lexbuf, markerRange: range) =
let GrabXmlDocBeforeMarker (lexbuf: Lexbuf, markerRange: range) =
match lexbuf.BufferLocalStore.TryGetValue xmlDocKey with
| true, collector ->
let collector = unbox<XmlDocCollector>(collector)
let collector = unbox<XmlDocCollector> (collector)
PreXmlDoc.CreateFromGrabPoint(collector, markerRange.Start)
| _ ->
PreXmlDoc.Empty
| _ -> PreXmlDoc.Empty
let ReportInvalidXmlDocPositions (lexbuf: Lexbuf) =
let collector = getCollector lexbuf
......@@ -162,20 +161,21 @@ type LexerIfdefStack = LexerIfdefStackEntries
/// it reaches end of line or eof. The options are to continue with 'token' function
/// or to continue with 'skip' function.
type LexerEndlineContinuation =
| Token
| Token
| Skip of int * range: range
type LexerIfdefExpression =
| IfdefAnd of LexerIfdefExpression*LexerIfdefExpression
| IfdefOr of LexerIfdefExpression*LexerIfdefExpression
| IfdefAnd of LexerIfdefExpression * LexerIfdefExpression
| IfdefOr of LexerIfdefExpression * LexerIfdefExpression
| IfdefNot of LexerIfdefExpression
| IfdefId of string
let rec LexerIfdefEval (lookup: string -> bool) = function
| IfdefAnd (l, r) -> (LexerIfdefEval lookup l) && (LexerIfdefEval lookup r)
| IfdefOr (l, r) -> (LexerIfdefEval lookup l) || (LexerIfdefEval lookup r)
| IfdefNot e -> not (LexerIfdefEval lookup e)
| IfdefId id -> lookup id
let rec LexerIfdefEval (lookup: string -> bool) =
function
| IfdefAnd (l, r) -> (LexerIfdefEval lookup l) && (LexerIfdefEval lookup r)
| IfdefOr (l, r) -> (LexerIfdefEval lookup l) || (LexerIfdefEval lookup r)
| IfdefNot e -> not (LexerIfdefEval lookup e)
| IfdefId id -> lookup id
/// Ifdef F# lexer/parser state, held in the BufferLocalStore for the lexer.
/// Used to capture #if, #else and #endif as syntax trivia.
......@@ -183,47 +183,47 @@ module LexbufIfdefStore =
// The key into the BufferLocalStore used to hold the compiler directives
let private ifDefKey = "Ifdef"
let private getStore (lexbuf: Lexbuf): ResizeArray<ConditionalDirectiveTrivia> =
let private getStore (lexbuf: Lexbuf) : ResizeArray<ConditionalDirectiveTrivia> =
match lexbuf.BufferLocalStore.TryGetValue ifDefKey with
| true, store -> store
| _ ->
let store = box (ResizeArray<ConditionalDirectiveTrivia>())
lexbuf.BufferLocalStore[ifDefKey] <- store
lexbuf.BufferLocalStore[ ifDefKey ] <- store
store
|> unbox<ResizeArray<ConditionalDirectiveTrivia>>
let private mkRangeWithoutLeadingWhitespace (lexed:string) (m:range): range =
let startColumn = lexed.Length - lexed.TrimStart().Length
mkFileIndexRange m.FileIndex (mkPos m.StartLine startColumn) m.End
let SaveIfHash (lexbuf: Lexbuf, lexed:string, expr: LexerIfdefExpression, range: range) =
let private mkRangeWithoutLeadingWhitespace (lexed: string) (m: range) : range =
let startColumn = lexed.Length - lexed.TrimStart().Length
mkFileIndexRange m.FileIndex (mkPos m.StartLine startColumn) m.End
let SaveIfHash (lexbuf: Lexbuf, lexed: string, expr: LexerIfdefExpression, range: range) =
let store = getStore lexbuf
let expr =
let rec visit (expr: LexerIfdefExpression) : IfDirectiveExpression =
match expr with
| LexerIfdefExpression.IfdefAnd(l,r) -> IfDirectiveExpression.And(visit l, visit r)
| LexerIfdefExpression.IfdefOr(l, r) -> IfDirectiveExpression.Or(visit l, visit r)
| LexerIfdefExpression.IfdefAnd (l, r) -> IfDirectiveExpression.And(visit l, visit r)
| LexerIfdefExpression.IfdefOr (l, r) -> IfDirectiveExpression.Or(visit l, visit r)
| LexerIfdefExpression.IfdefNot e -> IfDirectiveExpression.Not(visit e)
| LexerIfdefExpression.IfdefId id -> IfDirectiveExpression.Ident id
visit expr
let m = mkRangeWithoutLeadingWhitespace lexed range
store.Add(ConditionalDirectiveTrivia.If(expr, m))
let SaveElseHash (lexbuf: Lexbuf, lexed:string, range: range) =
let SaveElseHash (lexbuf: Lexbuf, lexed: string, range: range) =
let store = getStore lexbuf
let m = mkRangeWithoutLeadingWhitespace lexed range
store.Add(ConditionalDirectiveTrivia.Else(m))
let SaveEndIfHash (lexbuf: Lexbuf, lexed:string, range: range) =
let SaveEndIfHash (lexbuf: Lexbuf, lexed: string, range: range) =
let store = getStore lexbuf
let m = mkRangeWithoutLeadingWhitespace lexed range
store.Add(ConditionalDirectiveTrivia.EndIf(m))
let GetTrivia (lexbuf: Lexbuf): ConditionalDirectiveTrivia list =
let GetTrivia (lexbuf: Lexbuf) : ConditionalDirectiveTrivia list =
let store = getStore lexbuf
Seq.toList store
......@@ -232,12 +232,12 @@ module LexbufCommentStore =
// The key into the BufferLocalStore used to hold the compiler directives
let private commentKey = "Comments"
let private getStore (lexbuf: Lexbuf): ResizeArray<CommentTrivia> =
let private getStore (lexbuf: Lexbuf) : ResizeArray<CommentTrivia> =
match lexbuf.BufferLocalStore.TryGetValue commentKey with
| true, store -> store
| _ ->
let store = box (ResizeArray<CommentTrivia>())
lexbuf.BufferLocalStore[commentKey] <- store
lexbuf.BufferLocalStore[ commentKey ] <- store
store
|> unbox<ResizeArray<CommentTrivia>>
......@@ -251,11 +251,11 @@ module LexbufCommentStore =
let m = unionRanges startRange endRange
store.Add(CommentTrivia.BlockComment(m))
let GetComments (lexbuf: Lexbuf): CommentTrivia list =
let GetComments (lexbuf: Lexbuf) : CommentTrivia list =
let store = getStore lexbuf
Seq.toList store
let ClearComments (lexbuf: Lexbuf): unit =
let ClearComments (lexbuf: Lexbuf) : unit =
lexbuf.BufferLocalStore.Remove(commentKey) |> ignore
//------------------------------------------------------------------------
......@@ -270,13 +270,39 @@ type LexerStringStyle =
[<RequireQualifiedAccess; Struct>]
type LexerStringKind =
{ IsByteString: bool
IsInterpolated: bool
IsInterpolatedFirst: bool }
static member String = { IsByteString = false; IsInterpolated = false; IsInterpolatedFirst=false }
static member ByteString = { IsByteString = true; IsInterpolated = false; IsInterpolatedFirst=false }
static member InterpolatedStringFirst = { IsByteString = false; IsInterpolated = true; IsInterpolatedFirst=true }
static member InterpolatedStringPart = { IsByteString = false; IsInterpolated = true; IsInterpolatedFirst=false }
{
IsByteString: bool
IsInterpolated: bool
IsInterpolatedFirst: bool
}
static member String =
{
IsByteString = false
IsInterpolated = false
IsInterpolatedFirst = false
}
static member ByteString =
{
IsByteString = true
IsInterpolated = false
IsInterpolatedFirst = false
}
static member InterpolatedStringFirst =
{
IsByteString = false
IsInterpolated = true
IsInterpolatedFirst = true
}
static member InterpolatedStringPart =
{
IsByteString = false
IsInterpolated = true
IsInterpolatedFirst = false
}
/// Represents the degree of nesting of '{..}' and the style of the string to continue afterwards, in an interpolation fill.
/// Nesting counters and styles of outer interpolating strings are pushed on this stack.
......@@ -291,36 +317,46 @@ type LexerInterpolatedStringNesting = (int * LexerStringStyle * range) list
type LexerContinuation =
| Token of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting
| IfDefSkip of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * int * range: range
| String of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * style: LexerStringStyle * kind: LexerStringKind * range: range
| String of
ifdef: LexerIfdefStackEntries *
nesting: LexerInterpolatedStringNesting *
style: LexerStringStyle *
kind: LexerStringKind *
range: range
| Comment of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * int * range: range
| SingleLineComment of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * int * range: range
| StringInComment of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * style: LexerStringStyle * int * range: range
| StringInComment of
ifdef: LexerIfdefStackEntries *
nesting: LexerInterpolatedStringNesting *
style: LexerStringStyle *
int *
range: range
| MLOnly of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * range: range
| EndLine of ifdef: LexerIfdefStackEntries * nesting: LexerInterpolatedStringNesting * LexerEndlineContinuation
static member Default = LexCont.Token([],[])
static member Default = LexCont.Token([], [])
member x.LexerIfdefStack =
match x with
| LexCont.Token (ifdef=ifd)
| LexCont.IfDefSkip (ifdef=ifd)
| LexCont.String (ifdef=ifd)
| LexCont.Comment (ifdef=ifd)
| LexCont.SingleLineComment (ifdef=ifd)
| LexCont.StringInComment (ifdef=ifd)
| LexCont.EndLine (ifdef=ifd)
| LexCont.MLOnly (ifdef=ifd) -> ifd
| LexCont.Token (ifdef = ifd)
| LexCont.IfDefSkip (ifdef = ifd)
| LexCont.String (ifdef = ifd)
| LexCont.Comment (ifdef = ifd)
| LexCont.SingleLineComment (ifdef = ifd)
| LexCont.StringInComment (ifdef = ifd)
| LexCont.EndLine (ifdef = ifd)
| LexCont.MLOnly (ifdef = ifd) -> ifd
member x.LexerInterpStringNesting =
match x with
| LexCont.Token (nesting=nesting)
| LexCont.IfDefSkip (nesting=nesting)
| LexCont.String (nesting=nesting)
| LexCont.Comment (nesting=nesting)
| LexCont.SingleLineComment (nesting=nesting)
| LexCont.StringInComment (nesting=nesting)
| LexCont.EndLine (nesting=nesting)
| LexCont.MLOnly (nesting=nesting) -> nesting
| LexCont.Token (nesting = nesting)
| LexCont.IfDefSkip (nesting = nesting)
| LexCont.String (nesting = nesting)
| LexCont.Comment (nesting = nesting)
| LexCont.SingleLineComment (nesting = nesting)
| LexCont.StringInComment (nesting = nesting)
| LexCont.EndLine (nesting = nesting)
| LexCont.MLOnly (nesting = nesting) -> nesting
and LexCont = LexerContinuation
......@@ -328,44 +364,42 @@ and LexCont = LexerContinuation
// Parse IL assembly code
//------------------------------------------------------------------------
let ParseAssemblyCodeInstructions s reportLibraryOnlyFeatures langVersion m : IL.ILInstr[] =
let ParseAssemblyCodeInstructions s reportLibraryOnlyFeatures langVersion m : IL.ILInstr[] =
#if NO_INLINE_IL_PARSER
ignore s
ignore isFeatureSupported
errorR(Error((193, "Inline IL not valid in a hosted environment"), m))
[| |]
errorR (Error((193, "Inline IL not valid in a hosted environment"), m))
[||]
#else
try
AsciiParser.ilInstrs
AsciiLexer.token
(StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, s))
AsciiParser.ilInstrs AsciiLexer.token (StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, s))
with _ ->
errorR(Error(FSComp.SR.astParseEmbeddedILError(), m)); [||]
errorR (Error(FSComp.SR.astParseEmbeddedILError (), m))
[||]
#endif
let ParseAssemblyCodeType s reportLibraryOnlyFeatures langVersion m =
ignore s
#if NO_INLINE_IL_PARSER
errorR(Error((193, "Inline IL not valid in a hosted environment"), m))
errorR (Error((193, "Inline IL not valid in a hosted environment"), m))
IL.PrimaryAssemblyILGlobals.typ_Object
#else
try
AsciiParser.ilType
AsciiLexer.token
(StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, s))
AsciiParser.ilType AsciiLexer.token (StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, s))
with RecoverableParseError ->
errorR(Error(FSComp.SR.astParseEmbeddedILTypeError(), m));
IL.PrimaryAssemblyILGlobals.typ_Object
errorR (Error(FSComp.SR.astParseEmbeddedILTypeError (), m))
IL.PrimaryAssemblyILGlobals.typ_Object
#endif
let grabXmlDocAtRangeStart(parseState: IParseState, optAttributes: SynAttributeList list, range: range) =
let grabXmlDocAtRangeStart (parseState: IParseState, optAttributes: SynAttributeList list, range: range) =
let grabPoint =
match optAttributes with
| [] -> range
| h :: _ -> h.Range
LexbufLocalXmlDocStore.GrabXmlDocBeforeMarker(parseState.LexBuffer, grabPoint)
let grabXmlDoc(parseState: IParseState, optAttributes: SynAttributeList list, elemIdx) =
grabXmlDocAtRangeStart(parseState, optAttributes, rhs parseState elemIdx)
let grabXmlDoc (parseState: IParseState, optAttributes: SynAttributeList list, elemIdx) =
grabXmlDocAtRangeStart (parseState, optAttributes, rhs parseState elemIdx)
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
/// Some general F# utilities for mangling / unmangling / manipulating names.
/// Anything to do with special names of identifiers and other lexical rules
/// Anything to do with special names of identifiers and other lexical rules
module public FSharp.Compiler.Syntax.PrettyNaming
open System
......@@ -19,109 +19,123 @@ open FSharp.Compiler.Text.Layout
// Operator name compilation
//-----------------------------------------------------------------------
let [<Literal>] parenGet = ".()"
let [<Literal>] parenSet = ".()<-"
let [<Literal>] qmark = "?"
let [<Literal>] qmarkSet = "?<-"
[<Literal>]
let parenGet = ".()"
[<Literal>]
let parenSet = ".()<-"
[<Literal>]
let qmark = "?"
[<Literal>]
let qmarkSet = "?<-"
/// Prefix for compiled (mangled) operator names.
let [<Literal>] opNamePrefix = "op_"
let opNameTable =
[|("[]", "op_Nil")
("::", "op_ColonColon")
("+", "op_Addition")
("~%", "op_Splice")
("~%%", "op_SpliceUntyped")
("~++", "op_Increment")
("~--", "op_Decrement")
("-", "op_Subtraction")
("*", "op_Multiply")
("**", "op_Exponentiation")
("/", "op_Division")
("@", "op_Append")
("^", "op_Concatenate")
("%", "op_Modulus")
("&&&", "op_BitwiseAnd")
("|||", "op_BitwiseOr")
("^^^", "op_ExclusiveOr")
("<<<", "op_LeftShift")
("~~~", "op_LogicalNot")
(">>>", "op_RightShift")
("~+", "op_UnaryPlus")
("~-", "op_UnaryNegation")
("~&", "op_AddressOf")
("~&&", "op_IntegerAddressOf")
("&&", "op_BooleanAnd")
("||", "op_BooleanOr")
("<=", "op_LessThanOrEqual")
("=", "op_Equality")
("<>", "op_Inequality")
(">=", "op_GreaterThanOrEqual")
("<", "op_LessThan")
(">", "op_GreaterThan")
("|>", "op_PipeRight")
("||>", "op_PipeRight2")
("|||>", "op_PipeRight3")
("<|", "op_PipeLeft")
("<||", "op_PipeLeft2")
("<|||", "op_PipeLeft3")
("!", "op_Dereference")
(">>", "op_ComposeRight")
("<<", "op_ComposeLeft")
("<< >>", "op_TypedQuotationUnicode")
("<<| |>>", "op_ChevronsBar")
("<@ @>", "op_Quotation")
("<@@ @@>", "op_QuotationUntyped")
("+=", "op_AdditionAssignment")
("-=", "op_SubtractionAssignment")
("*=", "op_MultiplyAssignment")
("/=", "op_DivisionAssignment")
("..", "op_Range")
(".. ..", "op_RangeStep")
(qmark, "op_Dynamic")
(qmarkSet, "op_DynamicAssignment")
(parenGet, "op_ArrayLookup")
(parenSet, "op_ArrayAssign")
[<Literal>]
let opNamePrefix = "op_"
let opNameTable =
[|
("[]", "op_Nil")
("::", "op_ColonColon")
("+", "op_Addition")
("~%", "op_Splice")
("~%%", "op_SpliceUntyped")
("~++", "op_Increment")
("~--", "op_Decrement")
("-", "op_Subtraction")
("*", "op_Multiply")
("**", "op_Exponentiation")
("/", "op_Division")
("@", "op_Append")
("^", "op_Concatenate")
("%", "op_Modulus")
("&&&", "op_BitwiseAnd")
("|||", "op_BitwiseOr")
("^^^", "op_ExclusiveOr")
("<<<", "op_LeftShift")
("~~~", "op_LogicalNot")
(">>>", "op_RightShift")
("~+", "op_UnaryPlus")
("~-", "op_UnaryNegation")
("~&", "op_AddressOf")
("~&&", "op_IntegerAddressOf")
("&&", "op_BooleanAnd")
("||", "op_BooleanOr")
("<=", "op_LessThanOrEqual")
("=", "op_Equality")
("<>", "op_Inequality")
(">=", "op_GreaterThanOrEqual")
("<", "op_LessThan")
(">", "op_GreaterThan")
("|>", "op_PipeRight")
("||>", "op_PipeRight2")
("|||>", "op_PipeRight3")
("<|", "op_PipeLeft")
("<||", "op_PipeLeft2")
("<|||", "op_PipeLeft3")
("!", "op_Dereference")
(">>", "op_ComposeRight")
("<<", "op_ComposeLeft")
("<< >>", "op_TypedQuotationUnicode")
("<<| |>>", "op_ChevronsBar")
("<@ @>", "op_Quotation")
("<@@ @@>", "op_QuotationUntyped")
("+=", "op_AdditionAssignment")
("-=", "op_SubtractionAssignment")
("*=", "op_MultiplyAssignment")
("/=", "op_DivisionAssignment")
("..", "op_Range")
(".. ..", "op_RangeStep")
(qmark, "op_Dynamic")
(qmarkSet, "op_DynamicAssignment")
(parenGet, "op_ArrayLookup")
(parenSet, "op_ArrayAssign")
|]
let opCharTranslateTable =
[|( '>', "Greater")
( '<', "Less")
( '+', "Plus")
( '-', "Minus")
( '*', "Multiply")
( '=', "Equals")
( '~', "Twiddle")
( '%', "Percent")
( '.', "Dot")
( '$', "Dollar")
( '&', "Amp")
( '|', "Bar")
( '@', "At")
( '#', "Hash")
( '^', "Hat")
( '!', "Bang")
( '?', "Qmark")
( '/', "Divide")
( ':', "Colon")
( '(', "LParen")
( ',', "Comma")
( ')', "RParen")
( ' ', "Space")
( '[', "LBrack")
( ']', "RBrack") |]
[|
('>', "Greater")
('<', "Less")
('+', "Plus")
('-', "Minus")
('*', "Multiply")
('=', "Equals")
('~', "Twiddle")
('%', "Percent")
('.', "Dot")
('$', "Dollar")
('&', "Amp")
('|', "Bar")
('@', "At")
('#', "Hash")
('^', "Hat")
('!', "Bang")
('?', "Qmark")
('/', "Divide")
(':', "Colon")
('(', "LParen")
(',', "Comma")
(')', "RParen")
(' ', "Space")
('[', "LBrack")
(']', "RBrack")
|]
/// The set of characters usable in custom operators.
let opCharSet =
let t = HashSet<_>()
for c, _ in opCharTranslateTable do
t.Add(c) |> ignore
t
/// The characters that are allowed to be the first character of an identifier.
let IsIdentifierFirstCharacter c =
if c = '_' then true
if c = '_' then
true
else
match Char.GetUnicodeCategory c with
// Letters
......@@ -135,7 +149,8 @@ let IsIdentifierFirstCharacter c =
/// The characters that are allowed to be in an identifier.
let IsIdentifierPartCharacter c =
if c = '\'' then true // Tick
if c = '\'' then
true // Tick
else
match Char.GetUnicodeCategory c with
// Letters
......@@ -155,120 +170,130 @@ let IsIdentifierPartCharacter c =
| _ -> false
/// Keywords paired with their descriptions. Used in completion and quick info.
let keywordsWithDescription : (string * string) list =
[ "abstract", FSComp.SR.keywordDescriptionAbstract()
"and", FSComp.SR.keyworkDescriptionAnd()
"as", FSComp.SR.keywordDescriptionAs()
"assert", FSComp.SR.keywordDescriptionAssert()
"base", FSComp.SR.keywordDescriptionBase()
"begin", FSComp.SR.keywordDescriptionBegin()
"class", FSComp.SR.keywordDescriptionClass()
"const", FSComp.SR.keywordDescriptionConst()
"default", FSComp.SR.keywordDescriptionDefault()
"delegate", FSComp.SR.keywordDescriptionDelegate()
"do", FSComp.SR.keywordDescriptionDo()
"done", FSComp.SR.keywordDescriptionDone()
"downcast", FSComp.SR.keywordDescriptionDowncast()
"downto", FSComp.SR.keywordDescriptionDownto()
"elif", FSComp.SR.keywordDescriptionElif()
"else", FSComp.SR.keywordDescriptionElse()
"end", FSComp.SR.keywordDescriptionEnd()
"exception", FSComp.SR.keywordDescriptionException()
"extern", FSComp.SR.keywordDescriptionExtern()
"false", FSComp.SR.keywordDescriptionTrueFalse()
"finally", FSComp.SR.keywordDescriptionFinally()
"for", FSComp.SR.keywordDescriptionFor()
"fun", FSComp.SR.keywordDescriptionFun()
"function", FSComp.SR.keywordDescriptionFunction()
"global", FSComp.SR.keywordDescriptionGlobal()
"if", FSComp.SR.keywordDescriptionIf()
"in", FSComp.SR.keywordDescriptionIn()
"inherit", FSComp.SR.keywordDescriptionInherit()
"inline", FSComp.SR.keywordDescriptionInline()
"interface", FSComp.SR.keywordDescriptionInterface()
"internal", FSComp.SR.keywordDescriptionInternal()
"lazy", FSComp.SR.keywordDescriptionLazy()
"let", FSComp.SR.keywordDescriptionLet()
"let!", FSComp.SR.keywordDescriptionLetBang()
"match", FSComp.SR.keywordDescriptionMatch()
"match!", FSComp.SR.keywordDescriptionMatchBang()
"member", FSComp.SR.keywordDescriptionMember()
"module", FSComp.SR.keywordDescriptionModule()
"mutable", FSComp.SR.keywordDescriptionMutable()
"namespace", FSComp.SR.keywordDescriptionNamespace()
"new", FSComp.SR.keywordDescriptionNew()
"not", FSComp.SR.keywordDescriptionNot()
"null", FSComp.SR.keywordDescriptionNull()
"of", FSComp.SR.keywordDescriptionOf()
"open", FSComp.SR.keywordDescriptionOpen()
"or", FSComp.SR.keywordDescriptionOr()
"override", FSComp.SR.keywordDescriptionOverride()
"private", FSComp.SR.keywordDescriptionPrivate()
"public", FSComp.SR.keywordDescriptionPublic()
"rec", FSComp.SR.keywordDescriptionRec()
"return", FSComp.SR.keywordDescriptionReturn()
"return!", FSComp.SR.keywordDescriptionReturnBang()
"static", FSComp.SR.keywordDescriptionStatic()
"struct", FSComp.SR.keywordDescriptionStruct()
"then", FSComp.SR.keywordDescriptionThen()
"to", FSComp.SR.keywordDescriptionTo()
"true", FSComp.SR.keywordDescriptionTrueFalse()
"try", FSComp.SR.keywordDescriptionTry()
"type", FSComp.SR.keywordDescriptionType()
"upcast", FSComp.SR.keywordDescriptionUpcast()
"use", FSComp.SR.keywordDescriptionUse()
"use!", FSComp.SR.keywordDescriptionUseBang()
"val", FSComp.SR.keywordDescriptionVal()
"void", FSComp.SR.keywordDescriptionVoid()
"when", FSComp.SR.keywordDescriptionWhen()
"while", FSComp.SR.keywordDescriptionWhile()
"with", FSComp.SR.keywordDescriptionWith()
"yield", FSComp.SR.keywordDescriptionYield()
"yield!", FSComp.SR.keywordDescriptionYieldBang()
"->", FSComp.SR.keywordDescriptionRightArrow()
"<-", FSComp.SR.keywordDescriptionLeftArrow()
":>", FSComp.SR.keywordDescriptionCast()
":?>", FSComp.SR.keywordDescriptionDynamicCast()
"<@", FSComp.SR.keywordDescriptionTypedQuotation()
"@>", FSComp.SR.keywordDescriptionTypedQuotation()
"<@@", FSComp.SR.keywordDescriptionUntypedQuotation()
"@@>", FSComp.SR.keywordDescriptionUntypedQuotation() ]
let keywordsWithDescription: (string * string) list =
[
"abstract", FSComp.SR.keywordDescriptionAbstract ()
"and", FSComp.SR.keyworkDescriptionAnd ()
"as", FSComp.SR.keywordDescriptionAs ()
"assert", FSComp.SR.keywordDescriptionAssert ()
"base", FSComp.SR.keywordDescriptionBase ()
"begin", FSComp.SR.keywordDescriptionBegin ()
"class", FSComp.SR.keywordDescriptionClass ()
"const", FSComp.SR.keywordDescriptionConst ()
"default", FSComp.SR.keywordDescriptionDefault ()
"delegate", FSComp.SR.keywordDescriptionDelegate ()
"do", FSComp.SR.keywordDescriptionDo ()
"done", FSComp.SR.keywordDescriptionDone ()
"downcast", FSComp.SR.keywordDescriptionDowncast ()
"downto", FSComp.SR.keywordDescriptionDownto ()
"elif", FSComp.SR.keywordDescriptionElif ()
"else", FSComp.SR.keywordDescriptionElse ()
"end", FSComp.SR.keywordDescriptionEnd ()
"exception", FSComp.SR.keywordDescriptionException ()
"extern", FSComp.SR.keywordDescriptionExtern ()
"false", FSComp.SR.keywordDescriptionTrueFalse ()
"finally", FSComp.SR.keywordDescriptionFinally ()
"for", FSComp.SR.keywordDescriptionFor ()
"fun", FSComp.SR.keywordDescriptionFun ()
"function", FSComp.SR.keywordDescriptionFunction ()
"global", FSComp.SR.keywordDescriptionGlobal ()
"if", FSComp.SR.keywordDescriptionIf ()
"in", FSComp.SR.keywordDescriptionIn ()
"inherit", FSComp.SR.keywordDescriptionInherit ()
"inline", FSComp.SR.keywordDescriptionInline ()
"interface", FSComp.SR.keywordDescriptionInterface ()
"internal", FSComp.SR.keywordDescriptionInternal ()
"lazy", FSComp.SR.keywordDescriptionLazy ()
"let", FSComp.SR.keywordDescriptionLet ()
"let!", FSComp.SR.keywordDescriptionLetBang ()
"match", FSComp.SR.keywordDescriptionMatch ()
"match!", FSComp.SR.keywordDescriptionMatchBang ()
"member", FSComp.SR.keywordDescriptionMember ()
"module", FSComp.SR.keywordDescriptionModule ()
"mutable", FSComp.SR.keywordDescriptionMutable ()
"namespace", FSComp.SR.keywordDescriptionNamespace ()
"new", FSComp.SR.keywordDescriptionNew ()
"not", FSComp.SR.keywordDescriptionNot ()
"null", FSComp.SR.keywordDescriptionNull ()
"of", FSComp.SR.keywordDescriptionOf ()
"open", FSComp.SR.keywordDescriptionOpen ()
"or", FSComp.SR.keywordDescriptionOr ()
"override", FSComp.SR.keywordDescriptionOverride ()
"private", FSComp.SR.keywordDescriptionPrivate ()
"public", FSComp.SR.keywordDescriptionPublic ()
"rec", FSComp.SR.keywordDescriptionRec ()
"return", FSComp.SR.keywordDescriptionReturn ()
"return!", FSComp.SR.keywordDescriptionReturnBang ()
"static", FSComp.SR.keywordDescriptionStatic ()
"struct", FSComp.SR.keywordDescriptionStruct ()
"then", FSComp.SR.keywordDescriptionThen ()
"to", FSComp.SR.keywordDescriptionTo ()
"true", FSComp.SR.keywordDescriptionTrueFalse ()
"try", FSComp.SR.keywordDescriptionTry ()
"type", FSComp.SR.keywordDescriptionType ()
"upcast", FSComp.SR.keywordDescriptionUpcast ()
"use", FSComp.SR.keywordDescriptionUse ()
"use!", FSComp.SR.keywordDescriptionUseBang ()
"val", FSComp.SR.keywordDescriptionVal ()
"void", FSComp.SR.keywordDescriptionVoid ()
"when", FSComp.SR.keywordDescriptionWhen ()
"while", FSComp.SR.keywordDescriptionWhile ()
"with", FSComp.SR.keywordDescriptionWith ()
"yield", FSComp.SR.keywordDescriptionYield ()
"yield!", FSComp.SR.keywordDescriptionYieldBang ()
"->", FSComp.SR.keywordDescriptionRightArrow ()
"<-", FSComp.SR.keywordDescriptionLeftArrow ()
":>", FSComp.SR.keywordDescriptionCast ()
":?>", FSComp.SR.keywordDescriptionDynamicCast ()
"<@", FSComp.SR.keywordDescriptionTypedQuotation ()
"@>", FSComp.SR.keywordDescriptionTypedQuotation ()
"<@@", FSComp.SR.keywordDescriptionUntypedQuotation ()
"@@>", FSComp.SR.keywordDescriptionUntypedQuotation ()
]
let keywordLookup = set (List.map fst keywordsWithDescription)
// Some legacy compat operator names are not encode using op_XYZ and this
// do not carry sufficient information to distinguish between
// let (or) x y = x || y
// let ``or`` x y = x || y
// let (land) x y = x || y
// let ``land`` x y = x || y
// do not carry sufficient information to distinguish between
// let (or) x y = x || y
// let ``or`` x y = x || y
// let (land) x y = x || y
// let ``land`` x y = x || y
// All are deprecated except 'mod'. All except those two get double-backticks
let IsUnencodedOpName (name: string) =
let IsUnencodedOpName (name: string) =
match name with
| "mod" -> true
| _ -> false
let IsUnencodedLegacyOpName (name: string) =
let IsUnencodedLegacyOpName (name: string) =
match name with
| "or" | "land" | "lor" | "lsl"
| "lsr" | "asr" | "lxor" -> true
| "or"
| "land"
| "lor"
| "lsl"
| "lsr"
| "asr"
| "lxor" -> true
| _ -> false
let IsIdentifierName (name: string) =
not (keywordLookup.Contains name) &&
not (IsUnencodedOpName name) &&
not (IsUnencodedLegacyOpName name) &&
let nameLen = name.Length
nameLen > 0 &&
IsIdentifierFirstCharacter name[0] &&
let rec loop i = (i >= nameLen || (IsIdentifierPartCharacter(name[i]) && loop (i+1)))
loop 1
not (keywordLookup.Contains name)
&& not (IsUnencodedOpName name)
&& not (IsUnencodedLegacyOpName name)
&& let nameLen = name.Length in
nameLen > 0
&& IsIdentifierFirstCharacter name[0]
&& let rec loop i =
(i >= nameLen || (IsIdentifierPartCharacter(name[i]) && loop (i + 1))) in
loop 1
let rec isCoreActivePatternName (name: string) idx seenNonOpChar =
if idx = name.Length - 1 then
seenNonOpChar
else
let c = name[idx]
if opCharSet.Contains(c) && c <> '|' && c <> ' ' then
false
else
......@@ -278,12 +303,13 @@ let rec isCoreActivePatternName (name: string) idx seenNonOpChar =
let IsActivePatternName (name: string) =
// The name must contain at least one character between the starting and ending delimiters.
let nameLen = name.Length
if nameLen < 3 || name[0] <> '|' || name[nameLen - 1] <> '|' then
false
else
isCoreActivePatternName name 1 false
/// Returns `true` if given string is an operator display name (DisplayName), e.g.
/// Returns `true` if given string is an operator display name (DisplayName), e.g.
/// (::)
/// ([])
/// (|>>)
......@@ -301,6 +327,7 @@ let IsOperatorDisplayName (name: string) =
true
else
let c = name[idx]
if not (opCharSet.Contains(c)) || c = ' ' then
false
else
......@@ -308,12 +335,18 @@ let IsOperatorDisplayName (name: string) =
let skipParens2 = name.StartsWithOrdinal("( ") && name.EndsWithOrdinal(" )")
let skipParens1 = name.StartsWithOrdinal("(") && name.EndsWithOrdinal(")")
let skip = if skipParens2 then 2 elif skipParens1 then 1 else 0
let skip =
if skipParens2 then 2
elif skipParens1 then 1
else 0
let startIndex = skip
let endIndex = name.Length - skip
(startIndex < endIndex && loop name startIndex endIndex) ||
(name = ".. ..") ||
(name = "(.. ..)")
(startIndex < endIndex && loop name startIndex endIndex)
|| (name = ".. ..")
|| (name = "(.. ..)")
//IsOperatorDisplayName "+"
//IsOperatorDisplayName "(+)"
......@@ -325,8 +358,7 @@ let IsOperatorDisplayName (name: string) =
//IsOperatorDisplayName "( )" // false
//IsOperatorDisplayName "( +)" // false
let IsMangledOpName (name: string) =
name.StartsWithOrdinal(opNamePrefix)
let IsMangledOpName (name: string) = name.StartsWithOrdinal(opNamePrefix)
/// Compiles a custom operator into a mangled operator name.
/// For example, "!%" becomes "op_DereferencePercent".
......@@ -336,8 +368,10 @@ let IsMangledOpName (name: string) =
let compileCustomOpName =
let t2 =
let t2 = Dictionary<_, _> opCharTranslateTable.Length
for x, y in opCharTranslateTable do
t2.Add (x, y)
t2.Add(x, y)
t2
/// The maximum length of the name for a custom operator character.
......@@ -354,28 +388,35 @@ let compileCustomOpName =
fun opp ->
// Has this operator already been compiled?
compiledOperators.GetOrAdd(opp, fun (op: string) ->
let opLength = op.Length
let sb = StringBuilder(opNamePrefix, opNamePrefix.Length + (opLength * maxOperatorNameLength))
for i = 0 to opLength - 1 do
let c = op[i]
match t2.TryGetValue c with
| true, x ->
sb.Append(x) |> ignore
| false, _ ->
sb.Append(c) |> ignore
/// The compiled (mangled) operator name.
let opName = sb.ToString ()
// Cache the compiled name so it can be reused.
opName)
compiledOperators.GetOrAdd(
opp,
fun (op: string) ->
let opLength = op.Length
let sb =
StringBuilder(opNamePrefix, opNamePrefix.Length + (opLength * maxOperatorNameLength))
for i = 0 to opLength - 1 do
let c = op[i]
match t2.TryGetValue c with
| true, x -> sb.Append(x) |> ignore
| false, _ -> sb.Append(c) |> ignore
/// The compiled (mangled) operator name.
let opName = sb.ToString()
// Cache the compiled name so it can be reused.
opName
)
/// Maps the built-in F# operators to their mangled operator names.
let standardOpNames =
let opNames = Dictionary<_, _> (opNameTable.Length, StringComparer.Ordinal)
let opNames = Dictionary<_, _>(opNameTable.Length, StringComparer.Ordinal)
for x, y in opNameTable do
opNames.Add (x, y)
opNames.Add(x, y)
opNames
let CompileOpName op =
......@@ -411,17 +452,17 @@ let decompileCustomOpName =
| true, op -> op
| false, _ ->
let opNameLen = opName.Length
/// Function which decompiles the mangled operator name back into a string of operator characters.
/// Returns None if the name contains text which doesn't correspond to an operator
/// otherwise returns Some containing the original operator.
let rec decompile (sb : StringBuilder) idx =
/// otherwise returns Some containing the original operator.
let rec decompile (sb: StringBuilder) idx =
// Have we reached the end of 'opName'?
if idx = opNameLen then
// Finished decompiling.
// Cache the decompiled operator before returning so it can be reused.
let decompiledOp = sb.ToString ()
decompiledOperators.TryAdd (opName, decompiledOp) |> ignore
let decompiledOp = sb.ToString()
decompiledOperators.TryAdd(opName, decompiledOp) |> ignore
decompiledOp
else
let choice =
......@@ -430,10 +471,12 @@ let decompileCustomOpName =
// If this operator character name is longer than the remaining piece of 'opName',
// it's obviously not a match.
let opCharNameLen = opCharName.Length
if opNameLen - idx < opCharNameLen then false
if opNameLen - idx < opCharNameLen then
false
else
// Does 'opCharName' match the current position in 'opName'?
String.Compare (opName, idx, opCharName, 0, opCharNameLen, StringComparison.Ordinal) = 0)
String.Compare(opName, idx, opCharName, 0, opCharNameLen, StringComparison.Ordinal) = 0)
match choice with
| None ->
......@@ -447,21 +490,24 @@ let decompileCustomOpName =
decompile sb (idx + opCharName.Length)
let opNamePrefixLen = opNamePrefix.Length
let sb =
/// The maximum number of operator characters that could be contained in the
/// decompiled operator given the length of the mangled custom operator name.
let maxPossibleOpCharCount = (opNameLen - opNamePrefixLen) / minOperatorNameLength
StringBuilder maxPossibleOpCharCount
// Start decompiling just after the operator prefix.
decompile sb opNamePrefixLen
/// Maps the mangled operator names of built-in F# operators back to the operators.
let standardOpsDecompile =
let ops = Dictionary<string, string> (opNameTable.Length, StringComparer.Ordinal)
let ops = Dictionary<string, string>(opNameTable.Length, StringComparer.Ordinal)
for x, y in opNameTable do
ops.Add(y, x)
ops
let DecompileOpName opName =
......@@ -474,33 +520,35 @@ let DecompileOpName opName =
opName
let DoesIdentifierNeedBackticks (name: string) : bool =
not (IsUnencodedOpName name) &&
not (IsIdentifierName name) &&
not (IsActivePatternName name)
not (IsUnencodedOpName name)
&& not (IsIdentifierName name)
&& not (IsActivePatternName name)
/// A utility to help determine if an identifier needs to be quoted
/// A utility to help determine if an identifier needs to be quoted
let AddBackticksToIdentifierIfNeeded (name: string) : string =
if DoesIdentifierNeedBackticks name &&
not (name.StartsWithOrdinal("`")) &&
not (name.EndsWithOrdinal("`")) then
"``" + name + "``"
else
if
DoesIdentifierNeedBackticks name && not (name.StartsWithOrdinal("`"))
&& not (name.EndsWithOrdinal("`"))
then
"``" + name + "``"
else
name
/// Quote identifier with double backticks if needed, remove unnecessary double backticks quotation.
let NormalizeIdentifierBackticks (name: string) : string =
let s =
if name.StartsWithOrdinal("``") && name.EndsWithOrdinal("``") then
name[2..name.Length - 3]
else name
name[2 .. name.Length - 3]
else
name
AddBackticksToIdentifierIfNeeded s
let ConvertNameToDisplayName name =
AddBackticksToIdentifierIfNeeded name
let ConvertNameToDisplayName name = AddBackticksToIdentifierIfNeeded name
let ConvertValNameToDisplayName isBaseVal name =
if isBaseVal && name = "base" then
"base"
"base"
elif IsUnencodedOpName name || IsMangledOpName name || IsActivePatternName name then
let nm = DecompileOpName name
// Check for no decompilation, e.g. op_Implicit, op_NotAMangledOpName, op_A-B
......@@ -514,25 +562,28 @@ let ConvertValNameToDisplayName isBaseVal name =
"(" + nm + ")"
else
ConvertNameToDisplayName name
let ConvertNameToDisplayLayout nonOpLayout name =
if DoesIdentifierNeedBackticks name then
leftL (TaggedText.tagPunctuation "``") ^^ wordL (TaggedText.tagOperator name) ^^ rightL (TaggedText.tagPunctuation "``")
leftL (TaggedText.tagPunctuation "``")
^^ wordL (TaggedText.tagOperator name) ^^ rightL (TaggedText.tagPunctuation "``")
else
nonOpLayout name
let ConvertValNameToDisplayLayout isBaseVal nonOpLayout name =
if isBaseVal && name = "base" then
nonOpLayout "base"
nonOpLayout "base"
elif IsUnencodedOpName name || IsMangledOpName name || IsActivePatternName name then
let nm = DecompileOpName name
// Check for no decompilation, e.g. op_Implicit, op_NotAMangledOpName, op_A-B
if IsMangledOpName name && (nm = name) then
ConvertNameToDisplayLayout nonOpLayout name
elif nm.StartsWithOrdinal "*" || nm.EndsWithOrdinal "*" then
wordL (TaggedText.tagPunctuation "(") ^^ wordL (TaggedText.tagOperator nm) ^^ wordL (TaggedText.tagPunctuation ")")
wordL (TaggedText.tagPunctuation "(")
^^ wordL (TaggedText.tagOperator nm) ^^ wordL (TaggedText.tagPunctuation ")")
else
leftL (TaggedText.tagPunctuation "(") ^^ wordL (TaggedText.tagOperator nm) ^^ rightL (TaggedText.tagPunctuation ")")
leftL (TaggedText.tagPunctuation "(")
^^ wordL (TaggedText.tagOperator nm) ^^ rightL (TaggedText.tagPunctuation ")")
else
ConvertNameToDisplayLayout nonOpLayout name
......@@ -549,72 +600,104 @@ let opNameNullableEquals = CompileOpName "?="
let opNameNullableEqualsNullable = CompileOpName "?=?"
/// Is this character a part of a long identifier?
let IsLongIdentifierPartCharacter c =
c = '.'
|| IsIdentifierPartCharacter c
let IsLongIdentifierPartCharacter c = c = '.' || IsIdentifierPartCharacter c
let isTildeOnlyString (s: string) =
let rec loop (s: string) idx =
if idx >= s.Length then
true
elif s[idx] <> '~' then
false
else
loop s (idx + 1)
if idx >= s.Length then true
elif s[idx] <> '~' then false
else loop s (idx + 1)
loop s 0
let IsValidPrefixOperatorUse s =
if String.IsNullOrEmpty s then false else
match s with
| "?+" | "?-" | "+" | "-" | "+." | "-." | "%" | "%%" | "&" | "&&" -> true
| _ -> s[0] = '!' || isTildeOnlyString s
let IsValidPrefixOperatorDefinitionName s =
if String.IsNullOrEmpty s then false else
match s[0] with
| '~' ->
isTildeOnlyString s ||
if String.IsNullOrEmpty s then
false
else
match s with
| "~?+" | "~?-" | "~+" | "~-" | "~+." | "~-." | "~%" | "~%%" | "~&" | "~&&" -> true
| _ -> false
| "?+"
| "?-"
| "+"
| "-"
| "+."
| "-."
| "%"
| "%%"
| "&"
| "&&" -> true
| _ -> s[0] = '!' || isTildeOnlyString s
let IsValidPrefixOperatorDefinitionName s =
if String.IsNullOrEmpty s then
false
else
| '!' -> s <> "!="
| _ -> false
match s[0] with
| '~' ->
isTildeOnlyString s
||
match s with
| "~?+"
| "~?-"
| "~+"
| "~-"
| "~+."
| "~-."
| "~%"
| "~%%"
| "~&"
| "~&&" -> true
| _ -> false
| '!' -> s <> "!="
| _ -> false
let IsPrefixOperator s =
if String.IsNullOrEmpty s then false else
let s = DecompileOpName s
IsValidPrefixOperatorDefinitionName s
if String.IsNullOrEmpty s then
false
else
let s = DecompileOpName s
IsValidPrefixOperatorDefinitionName s
let IsPunctuation s =
if String.IsNullOrEmpty s then false else
match s with
| "," | ";" | "|" | ":" | "." | "*"
| "(" | ")"
| "[" | "]"
| "{" | "}"
| "<" | ">"
| "[|" | "|]"
| "[<" | ">]"
-> true
| _ -> false
if String.IsNullOrEmpty s then
false
else
match s with
| ","
| ";"
| "|"
| ":"
| "."
| "*"
| "("
| ")"
| "["
| "]"
| "{"
| "}"
| "<"
| ">"
| "[|"
| "|]"
| "[<"
| ">]" -> true
| _ -> false
let IsTernaryOperator s =
(DecompileOpName s = qmarkSet)
let IsTernaryOperator s = (DecompileOpName s = qmarkSet)
/// EQUALS, INFIX_COMPARE_OP, LESS, GREATER
let relational = [| "=";"!=";"<";">";"$"|]
let relational = [| "="; "!="; "<"; ">"; "$" |]
/// INFIX_AT_HAT_OP
let concat = [| "@";"^" |]
let concat = [| "@"; "^" |]
/// PLUS_MINUS_OP, MINUS
let plusMinus = [| "+"; "-" |]
/// PERCENT_OP, STAR, INFIX_STAR_DIV_MOD_OP
let otherMath = [| "*";"/";"%" |]
let otherMath = [| "*"; "/"; "%" |]
/// Characters ignored at the start of the operator name
/// when determining whether an operator is an infix operator.
......@@ -626,88 +709,129 @@ let ignoredChars = [| '.'; '?' |]
// The lexer defines the strings that lead to those tokens.
//------
// This function recognises these "infix operator" names.
let IsMangledInfixOperator mangled = (* where mangled is assumed to be a compiled name *)
let s = DecompileOpName mangled
let IsMangledInfixOperator mangled = (* where mangled is assumed to be a compiled name *)
let s = DecompileOpName mangled
let skipIgnoredChars = s.TrimStart(ignoredChars)
let afterSkipStartsWith prefix = skipIgnoredChars.StartsWithOrdinal(prefix)
let afterSkipStarts prefixes = Array.exists afterSkipStartsWith prefixes
let afterSkipStartsWith prefix =
skipIgnoredChars.StartsWithOrdinal(prefix)
let afterSkipStarts prefixes =
Array.exists afterSkipStartsWith prefixes
// The following conditions follow the declExpr infix clauses.
// The test corresponds to the lexer definition for the token.
s <> mangled &&
(s = ":=" || // COLON_EQUALS
afterSkipStartsWith "|" || // BAR_BAR, INFIX_BAR_OP
afterSkipStartsWith "&" || // AMP, AMP_AMP, INFIX_AMP_OP
afterSkipStarts relational || // EQUALS, INFIX_COMPARE_OP, LESS, GREATER
s = "$" || // DOLLAR
afterSkipStarts concat || // INFIX_AT_HAT_OP
s = "::" || // COLON_COLON
afterSkipStarts plusMinus || // PLUS_MINUS_OP, MINUS
afterSkipStarts otherMath || // PERCENT_OP, STAR, INFIX_STAR_DIV_MOD_OP
s = "**") // INFIX_STAR_STAR_OP
s <> mangled
&& ((s = // COLON_EQUALS
":=")
||
// BAR_BAR, INFIX_BAR_OP
afterSkipStartsWith "|"
||
// AMP, AMP_AMP, INFIX_AMP_OP
afterSkipStartsWith "&"
||
// EQUALS, INFIX_COMPARE_OP, LESS, GREATER
afterSkipStarts relational
||
// DOLLAR
(s = "$")
||
// INFIX_AT_HAT_OP
afterSkipStarts concat
||
// COLON_COLON
(s = "::")
||
// PLUS_MINUS_OP, MINUS
afterSkipStarts plusMinus
||
// PERCENT_OP, STAR, INFIX_STAR_DIV_MOD_OP
afterSkipStarts otherMath
||
// INFIX_STAR_STAR_OP
(s = "**"))
let (|Control|Equality|Relational|Indexer|FixedTypes|Other|) opName =
match opName with
| "&" | "or" | "&&" | "||" ->
Control
| "<>" | "=" ->
Equality
| "<" | ">" | "<=" | ">=" ->
Relational
| "<<" | "<|" | "<||" | "<||" | "|>" | "||>" | "|||>" | ">>" | "^" | ":=" | "@" ->
FixedTypes
| ".[]" ->
Indexer
| _ ->
Other
let [<Literal>] compilerGeneratedMarker = "@"
let [<Literal>] compilerGeneratedMarkerChar = '@'
| "&"
| "or"
| "&&"
| "||" -> Control
| "<>"
| "=" -> Equality
| "<"
| ">"
| "<="
| ">=" -> Relational
| "<<"
| "<|"
| "<||"
| "<||"
| "|>"
| "||>"
| "|||>"
| ">>"
| "^"
| ":="
| "@" -> FixedTypes
| ".[]" -> Indexer
| _ -> Other
[<Literal>]
let compilerGeneratedMarker = "@"
[<Literal>]
let compilerGeneratedMarkerChar = '@'
let IsCompilerGeneratedName (nm: string) =
nm.IndexOf compilerGeneratedMarkerChar <> -1
let CompilerGeneratedName nm =
if IsCompilerGeneratedName nm then nm else nm+compilerGeneratedMarker
if IsCompilerGeneratedName nm then
nm
else
nm + compilerGeneratedMarker
let GetBasicNameOfPossibleCompilerGeneratedName (name: string) =
match name.IndexOf(compilerGeneratedMarker, StringComparison.Ordinal) with
| -1 | 0 -> name
| n -> name[0..n-1]
match name.IndexOf(compilerGeneratedMarker, StringComparison.Ordinal) with
| -1
| 0 -> name
| n -> name[0 .. n - 1]
let CompilerGeneratedNameSuffix (basicName: string) suffix =
basicName+compilerGeneratedMarker+suffix
basicName + compilerGeneratedMarker + suffix
//-------------------------------------------------------------------------
// Handle mangled .NET generic type names
//-------------------------------------------------------------------------
let [<Literal>] mangledGenericTypeNameSym = '`'
//-------------------------------------------------------------------------
[<Literal>]
let mangledGenericTypeNameSym = '`'
let TryDemangleGenericNameAndPos (n: string) =
// check what comes after the symbol is a number
// check what comes after the symbol is a number
let pos = n.LastIndexOf mangledGenericTypeNameSym
if pos = -1 then ValueNone else
let mutable res = pos < n.Length - 1
let mutable i = pos + 1
while res && i < n.Length do
let char = n[i]
if not (char >= '0' && char <= '9') then
res <- false
i <- i + 1
if res then
ValueSome pos
else
if pos = -1 then
ValueNone
else
let mutable res = pos < n.Length - 1
let mutable i = pos + 1
while res && i < n.Length do
let char = n[i]
if not (char >= '0' && char <= '9') then res <- false
i <- i + 1
if res then ValueSome pos else ValueNone
type NameArityPair = NameArityPair of string * int
let DemangleGenericTypeNameWithPos pos (mangledName: string) =
mangledName.Substring(0, pos)
let DemangleGenericTypeNameWithPos pos (mangledName: string) = mangledName.Substring(0, pos)
let DecodeGenericTypeNameWithPos pos (mangledName: string) =
let res = DemangleGenericTypeNameWithPos pos mangledName
let num = mangledName.Substring(pos+1, mangledName.Length - pos - 1)
let num = mangledName.Substring(pos + 1, mangledName.Length - pos - 1)
NameArityPair(res, int32 num)
let DemangleGenericTypeName (mangledName: string) =
......@@ -730,53 +854,53 @@ let chopStringTo (s: string) (c: char) =
/// Try to chop "get_" or "set_" from a string
let TryChopPropertyName (s: string) =
// extract the logical name from any mangled name produced by MakeMemberDataAndMangledNameForMemberVal
if s.Length <= 4 then None else
if s.StartsWithOrdinal("get_") ||
s.StartsWithOrdinal("set_")
then Some (s.Substring(4, s.Length - 4))
if s.Length <= 4 then
None
else if s.StartsWithOrdinal("get_") || s.StartsWithOrdinal("set_") then
Some(s.Substring(4, s.Length - 4))
else
let s = chopStringTo s '.'
if s.StartsWithOrdinal("get_") ||
s.StartsWithOrdinal("set_")
then Some (s.Substring(4, s.Length - 4))
else None
let s = chopStringTo s '.'
if s.StartsWithOrdinal("get_") || s.StartsWithOrdinal("set_") then
Some(s.Substring(4, s.Length - 4))
else
None
/// Try to chop "get_" or "set_" from a string.
/// If the string does not start with "get_" or "set_", this function raises an exception.
let ChopPropertyName s =
match TryChopPropertyName s with
| None ->
failwithf "Invalid internal property name: '%s'" s
match TryChopPropertyName s with
| None -> failwithf "Invalid internal property name: '%s'" s
| Some res -> res
let SplitNamesForILPath (s : string) : string list =
if s.StartsWithOrdinal("``") && s.EndsWithOrdinal("``") && s.Length > 4 then [s.Substring(2, s.Length-4)] // identifier is enclosed in `` .. ``, so it is only a single element (this is very approximate)
else s.Split [| '.' ; '`' |] |> Array.toList // '.' chops members / namespaces / modules; '`' chops generic parameters for .NET types
let SplitNamesForILPath (s: string) : string list =
if s.StartsWithOrdinal("``") && s.EndsWithOrdinal("``") && s.Length > 4 then
[ s.Substring(2, s.Length - 4) ] // identifier is enclosed in `` .. ``, so it is only a single element (this is very approximate)
else
s.Split [| '.'; '`' |] |> Array.toList // '.' chops members / namespaces / modules; '`' chops generic parameters for .NET types
/// Return a string array delimited by the given separator.
/// Note that a quoted string is not going to be mangled into pieces.
let inline isNotQuotedQuotation (text: string) n = n > 0 && text[n-1] <> '\\'
/// Note that a quoted string is not going to be mangled into pieces.
let inline isNotQuotedQuotation (text: string) n = n > 0 && text[n - 1] <> '\\'
let splitAroundQuotation (text: string) (separator: char) =
let length = text.Length
let result = ResizeArray()
let mutable insideQuotation = false
let mutable start = 0
for i = 0 to length - 1 do
match text[i], insideQuotation with
// split when seeing a separator
| c, false when c = separator ->
| c, false when c = separator ->
result.Add(text.Substring(start, i - start))
insideQuotation <- false
start <- i + 1
| _, _ when i = length - 1 ->
result.Add(text.Substring(start, i - start + 1))
| _, _ when i = length - 1 -> result.Add(text.Substring(start, i - start + 1))
// keep reading if a separator is inside quotation
| c, true when c = separator ->
insideQuotation <- true
| c, true when c = separator -> insideQuotation <- true
// open or close quotation
| '\"', _ when isNotQuotedQuotation text i ->
insideQuotation <- not insideQuotation
| '\"', _ when isNotQuotedQuotation text i -> insideQuotation <- not insideQuotation
// keep reading
| _ -> ()
......@@ -784,63 +908,84 @@ let splitAroundQuotation (text: string) (separator: char) =
/// Return a string array delimited by the given separator up to the maximum number.
/// Note that a quoted string is not going to be mangled into pieces.
let splitAroundQuotationWithCount (text: string) (separator: char) (count: int)=
if count <= 1 then [| text |] else
let mangledText = splitAroundQuotation text separator
match mangledText.Length > count with
| true -> Array.append mangledText[0..(count-2)] [| mangledText[(count-1)..] |> String.concat (Char.ToString separator) |]
| false -> mangledText
let splitAroundQuotationWithCount (text: string) (separator: char) (count: int) =
if count <= 1 then
[| text |]
else
let mangledText = splitAroundQuotation text separator
match mangledText.Length > count with
| true -> Array.append mangledText[0 .. (count - 2)] [| mangledText[(count - 1) ..] |> String.concat (Char.ToString separator) |]
| false -> mangledText
[<Literal>]
let FSharpModuleSuffix = "Module"
[<Literal>]
let MangledGlobalName = "`global`"
let IllegalCharactersInTypeAndNamespaceNames = [| '.'; '+'; '$'; '&'; '['; ']'; '/'; '\\'; '*'; '\"'; '`' |]
type ActivePatternInfo =
| APInfo of bool * (string * range) list * range
let IllegalCharactersInTypeAndNamespaceNames =
[| '.'; '+'; '$'; '&'; '['; ']'; '/'; '\\'; '*'; '\"'; '`' |]
type ActivePatternInfo =
| APInfo of bool * (string * range) list * range
member x.IsTotal = let (APInfo(p, _, _)) = x in p
member x.IsTotal = let (APInfo (p, _, _)) = x in p
member x.ActiveTags = let (APInfo(_, tags, _)) = x in List.map fst tags
member x.ActiveTags = let (APInfo (_, tags, _)) = x in List.map fst tags
member x.ActiveTagsWithRanges = let (APInfo(_, tags, _)) = x in tags
member x.ActiveTagsWithRanges = let (APInfo (_, tags, _)) = x in tags
member x.Range = let (APInfo(_, _, m)) = x in m
member x.Range = let (APInfo (_, _, m)) = x in m
let ActivePatternInfoOfValName nm (m: range) =
let ActivePatternInfoOfValName nm (m: range) =
// Note: The approximate range calculations in this code assume the name is of the form "(|A|B|)" not "(| A | B |)"
// The ranges are used for IDE refactoring support etc. If names of the second type are used,
// renaming may be inaccurate/buggy. However names of the first form are dominant in F# code.
let rec loop (nm: string) (mp: range) =
let rec loop (nm: string) (mp: range) =
let n = nm.IndexOf '|'
if n > 0 then
let m1 = Range.mkRange mp.FileName mp.Start (Position.mkPos mp.StartLine (mp.StartColumn + n))
let m2 = Range.mkRange mp.FileName (Position.mkPos mp.StartLine (mp.StartColumn + n + 1)) mp.End
(nm[0..n-1], m1) :: loop nm[n+1..] m2
if n > 0 then
let m1 =
Range.mkRange mp.FileName mp.Start (Position.mkPos mp.StartLine (mp.StartColumn + n))
let m2 =
Range.mkRange mp.FileName (Position.mkPos mp.StartLine (mp.StartColumn + n + 1)) mp.End
(nm[0 .. n - 1], m1) :: loop nm[n + 1 ..] m2
else
let m1 = Range.mkRange mp.FileName mp.Start (Position.mkPos mp.StartLine (mp.StartColumn + nm.Length))
[(nm, m1)]
let m1 =
Range.mkRange mp.FileName mp.Start (Position.mkPos mp.StartLine (mp.StartColumn + nm.Length))
[ (nm, m1) ]
let nm = DecompileOpName nm
if IsActivePatternName nm then
if IsActivePatternName nm then
// Skip the '|' at each end when recovering ranges
let m0 = Range.mkRange m.FileName (Position.mkPos m.StartLine (m.StartColumn + 1)) (Position.mkPos m.EndLine (m.EndColumn - 1))
let names = loop nm[1..nm.Length-2] m0
let m0 =
Range.mkRange m.FileName (Position.mkPos m.StartLine (m.StartColumn + 1)) (Position.mkPos m.EndLine (m.EndColumn - 1))
let names = loop nm[1 .. nm.Length - 2] m0
let resH, resT = List.frontAndBack names
Some(if fst resT = "_" then APInfo(false, resH, m) else APInfo(true, names, m))
else
Some(
if fst resT = "_" then
APInfo(false, resH, m)
else
APInfo(true, names, m)
)
else
None
let mangleStaticStringArg (nm: string, v: string) =
let mangleStaticStringArg (nm: string, v: string) =
nm + "=" + "\"" + v.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""
let tryDemangleStaticStringArg (mangledText: string) =
match splitAroundQuotationWithCount mangledText '=' 2 with
| [| nm; v |] ->
if v.Length >= 2 then
Some(nm, v[1..v.Length-2].Replace("\\\\", "\\").Replace("\\\"", "\""))
Some(nm, v[ 1 .. v.Length - 2 ].Replace("\\\\", "\\").Replace("\\\"", "\""))
else
Some(nm, v)
| _ -> None
......@@ -848,26 +993,26 @@ let tryDemangleStaticStringArg (mangledText: string) =
exception InvalidMangledStaticArg of string
/// Demangle the static parameters
let demangleProvidedTypeName (typeLogicalName: string) =
if typeLogicalName.Contains "," then
let demangleProvidedTypeName (typeLogicalName: string) =
if typeLogicalName.Contains "," then
let pieces = splitAroundQuotation typeLogicalName ','
match pieces with
| [| x; "" |] -> x, [| |]
| [| x; "" |] -> x, [||]
| _ ->
let argNamesAndValues = pieces[1..] |> Array.choose tryDemangleStaticStringArg
if argNamesAndValues.Length = (pieces.Length - 1) then
pieces[0], argNamesAndValues
else
typeLogicalName, [| |]
else
typeLogicalName, [| |]
typeLogicalName, [||]
else
typeLogicalName, [||]
/// Mangle the static parameters for a provided type or method
let mangleProvidedTypeName (typeLogicalName, nonDefaultArgs) =
let nonDefaultArgsText =
nonDefaultArgs
|> Array.map mangleStaticStringArg
|> String.concat ","
let mangleProvidedTypeName (typeLogicalName, nonDefaultArgs) =
let nonDefaultArgsText =
nonDefaultArgs |> Array.map mangleStaticStringArg |> String.concat ","
if nonDefaultArgsText = "" then
typeLogicalName
......@@ -875,15 +1020,17 @@ let mangleProvidedTypeName (typeLogicalName, nonDefaultArgs) =
typeLogicalName + "," + nonDefaultArgsText
/// Mangle the static parameters for a provided type or method
let computeMangledNameWithoutDefaultArgValues(nm, staticArgs, defaultArgValues) =
let nonDefaultArgs =
(staticArgs, defaultArgValues)
||> Array.zip
|> Array.choose (fun (staticArg, (defaultArgName, defaultArgValue)) ->
let actualArgValue = string staticArg
match defaultArgValue with
let computeMangledNameWithoutDefaultArgValues (nm, staticArgs, defaultArgValues) =
let nonDefaultArgs =
(staticArgs, defaultArgValues)
||> Array.zip
|> Array.choose (fun (staticArg, (defaultArgName, defaultArgValue)) ->
let actualArgValue = string staticArg
match defaultArgValue with
| Some v when v = actualArgValue -> None
| _ -> Some (defaultArgName, actualArgValue))
| _ -> Some(defaultArgName, actualArgValue))
mangleProvidedTypeName (nm, nonDefaultArgs)
let outArgCompilerGeneratedName = "outArg"
......@@ -892,33 +1039,29 @@ let ExtraWitnessMethodName nm = nm + "$W"
/// Reuses generated union case field name objects for common field numbers
let mkUnionCaseFieldName =
let names =
[| 1 .. 10 |]
|> Array.map (fun i -> "Item" + string i)
let names = [| 1..10 |] |> Array.map (fun i -> "Item" + string i)
fun nFields i ->
match nFields with
| 0 | 1 -> "Item"
| 0
| 1 -> "Item"
| _ -> if i < 10 then names[i] else "Item" + string (i + 1)
/// Reuses generated exception field name objects for common field numbers
let mkExceptionFieldName =
let names =
[| 0 .. 9 |]
|> Array.map (fun i -> "Data" + string i)
let names = [| 0..9 |] |> Array.map (fun i -> "Data" + string i)
fun i ->
if i < 10 then names[i] else "Data" + string i
fun i -> if i < 10 then names[i] else "Data" + string i
/// The prefix of the names used for the fake namespace path added to all dynamic code entries in FSI.EXE
let FsiDynamicModulePrefix = "FSI_"
[<RequireQualifiedAccess>]
module FSharpLib =
let Root = "Microsoft.FSharp"
let RootPath = IL.splitNamespace Root
let Core = Root + ".Core"
let CorePath = IL.splitNamespace Core
let Root = "Microsoft.FSharp"
let RootPath = IL.splitNamespace Root
let Core = Root + ".Core"
let CorePath = IL.splitNamespace Core
[<RequireQualifiedAccess>]
module CustomOperations =
......@@ -927,7 +1070,8 @@ module CustomOperations =
let unassignedTyparName = "?"
let FormatAndOtherOverloadsString remainingOverloads = FSComp.SR.typeInfoOtherOverloads(remainingOverloads)
let FormatAndOtherOverloadsString remainingOverloads =
FSComp.SR.typeInfoOtherOverloads (remainingOverloads)
let GetLongNameFromString x = SplitNamesForILPath x
......@@ -939,16 +1083,18 @@ let FSharpOptimizationDataResourceName = "FSharpOptimizationData."
let FSharpSignatureDataResourceName = "FSharpSignatureData."
// For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers
// For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers
// don't complain when they see the resource. The prefix of these names must not be 'FSharpOptimizationData'
// or 'FSharpSignatureData'
let FSharpOptimizationDataResourceName2 = "FSharpOptimizationInfo."
let FSharpOptimizationDataResourceName2 = "FSharpOptimizationInfo."
let FSharpSignatureDataResourceName2 = "FSharpSignatureInfo."
let [<Literal>] suffixForVariablesThatMayNotBeEliminated = "$cont"
let [<Literal>] suffixForTupleElementAssignmentTarget = "$tupleElem"
[<Literal>]
let suffixForVariablesThatMayNotBeEliminated = "$cont"
let [<Literal>] stackVarPrefix = "__stack_"
[<Literal>]
let suffixForTupleElementAssignmentTarget = "$tupleElem"
[<Literal>]
let stackVarPrefix = "__stack_"
......@@ -12,13 +12,12 @@ open FSharp.Compiler.Xml
open FSharp.Compiler.SyntaxTrivia
[<Struct; NoEquality; NoComparison; DebuggerDisplay("{idText}")>]
type Ident (text: string, range: range) =
member _.idText = text
member _.idRange = range
override _.ToString() = text
type Ident(text: string, range: range) =
member _.idText = text
member _.idRange = range
override _.ToString() = text
type SynIdent =
| SynIdent of ident:Ident * trivia:IdentTrivia option
type SynIdent = SynIdent of ident: Ident * trivia: IdentTrivia option
type LongIdent = Ident list
......@@ -26,48 +25,61 @@ type SynLongIdent =
| SynLongIdent of id: LongIdent * dotRanges: range list * trivia: IdentTrivia option list
member this.Range =
match this with
| SynLongIdent([], _, _) -> failwith "rangeOfLidwd"
| SynLongIdent([id], [], _) -> id.idRange
| SynLongIdent([id], [m], _) -> unionRanges id.idRange m
| SynLongIdent(h :: t, [], _) -> unionRanges h.idRange (List.last t).idRange
| SynLongIdent(h :: t, dotRanges, _) -> unionRanges h.idRange (List.last t).idRange |> unionRanges (List.last dotRanges)
member this.LongIdent = match this with SynLongIdent(lid, _, _) -> lid
member this.Dots = match this with SynLongIdent(dotRanges = dots) -> dots
match this with
| SynLongIdent ([], _, _) -> failwith "rangeOfLidwd"
| SynLongIdent ([ id ], [], _) -> id.idRange
| SynLongIdent ([ id ], [ m ], _) -> unionRanges id.idRange m
| SynLongIdent (h :: t, [], _) -> unionRanges h.idRange (List.last t).idRange
| SynLongIdent (h :: t, dotRanges, _) -> unionRanges h.idRange (List.last t).idRange |> unionRanges (List.last dotRanges)
member this.LongIdent =
match this with
| SynLongIdent (lid, _, _) -> lid
member this.Dots =
match this with
| SynLongIdent (dotRanges = dots) -> dots
member this.Trivia =
match this with
| SynLongIdent(trivia = trivia) -> List.choose id trivia
| SynLongIdent (trivia = trivia) -> List.choose id trivia
member this.IdentsWithTrivia =
let (SynLongIdent(lid, _, trivia)) = this
let (SynLongIdent (lid, _, trivia)) = this
if lid.Length <> trivia.Length then
failwith "difference between idents and trivia"
else
List.zip lid trivia
|> List.map SynIdent
List.zip lid trivia |> List.map SynIdent
member this.ThereIsAnExtraDotAtTheEnd = match this with SynLongIdent(lid, dots, _) -> lid.Length = dots.Length
member this.ThereIsAnExtraDotAtTheEnd =
match this with
| SynLongIdent (lid, dots, _) -> lid.Length = dots.Length
member this.RangeWithoutAnyExtraDot =
match this with
| SynLongIdent([], _, _) -> failwith "rangeOfLidwd"
| SynLongIdent([id], _, _) -> id.idRange
| SynLongIdent(h :: t, dotRanges, _) ->
let nonExtraDots = if dotRanges.Length = t.Length then dotRanges else List.truncate t.Length dotRanges
unionRanges h.idRange (List.last t).idRange |> unionRanges (List.last nonExtraDots)
match this with
| SynLongIdent ([], _, _) -> failwith "rangeOfLidwd"
| SynLongIdent ([ id ], _, _) -> id.idRange
| SynLongIdent (h :: t, dotRanges, _) ->
let nonExtraDots =
if dotRanges.Length = t.Length then
dotRanges
else
List.truncate t.Length dotRanges
unionRanges h.idRange (List.last t).idRange
|> unionRanges (List.last nonExtraDots)
[<AutoOpen>]
module SynLongIdentHelpers =
[<Obsolete("Please use SynLongIdent or define a custom active pattern")>]
let (|LongIdentWithDots|) =
function
| SynLongIdent(lid, dots, _) -> lid, dots
| SynLongIdent (lid, dots, _) -> lid, dots
[<Obsolete("Please use SynLongIdent")>]
let LongIdentWithDots (lid, dots) = SynLongIdent(lid, dots, List.replicate lid.Length None)
let LongIdentWithDots (lid, dots) =
SynLongIdent(lid, dots, List.replicate lid.Length None)
[<RequireQualifiedAccess>]
type ParserDetail =
......@@ -87,8 +99,7 @@ type SynTypar =
member this.Range =
match this with
| SynTypar(id, _, _) ->
id.idRange
| SynTypar (id, _, _) -> id.idRange
[<Struct; RequireQualifiedAccess>]
type SynStringKind =
......@@ -138,21 +149,21 @@ type SynConst =
| UserNum of value: string * suffix: string
| String of text: string * synStringKind :SynStringKind * range: range
| String of text: string * synStringKind: SynStringKind * range: range
| Bytes of bytes: byte[] * synByteStringKind: SynByteStringKind * range: range
| UInt16s of uint16[]
| Measure of constant: SynConst * constantRange: range * SynMeasure
| SourceIdentifier of constant: string * value: string * range: range
member c.Range dflt =
match c with
| SynConst.String (_, _, m0)
| SynConst.Bytes (_, _, m0)
| SynConst.SourceIdentifier(_, _, m0) -> m0
| SynConst.SourceIdentifier (_, _, m0) -> m0
| _ -> dflt
[<NoEquality; NoComparison; RequireQualifiedAccess>]
......@@ -173,12 +184,12 @@ type SynMeasure =
| Anon of range: range
| Var of typar: SynTypar * range: range
| Paren of measure: SynMeasure * range: range
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynRationalConst =
| Integer of value: int32
| Rational of numerator: int32 * denominator: int32 * range: range
......@@ -193,7 +204,7 @@ type SynAccess =
| Private
override this.ToString () =
override this.ToString() =
match this with
| Public -> "Public"
| Internal -> "Internal"
......@@ -217,8 +228,7 @@ type DebugPointAtTry =
| No
[<RequireQualifiedAccess>]
type DebugPointAtLeafExpr =
| Yes of range
type DebugPointAtLeafExpr = Yes of range
[<RequireQualifiedAccess>]
type DebugPointAtWith =
......@@ -259,12 +269,11 @@ type DebugPointAtBinding =
member x.Combine(y: DebugPointAtBinding) =
match x, y with
| DebugPointAtBinding.Yes _ as g, _ -> g
| _, (DebugPointAtBinding.Yes _ as g) -> g
| DebugPointAtBinding.Yes _ as g, _ -> g
| _, (DebugPointAtBinding.Yes _ as g) -> g
| _ -> x
type SeqExprOnly =
| SeqExprOnly of bool
type SeqExprOnly = SeqExprOnly of bool
type BlockSeparator = range * pos option
......@@ -290,74 +299,46 @@ type SynBindingKind =
| Do
[<NoEquality; NoComparison>]
type SynTyparDecl =
| SynTyparDecl of attributes: SynAttributes * SynTypar
type SynTyparDecl = SynTyparDecl of attributes: SynAttributes * SynTypar
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynTypeConstraint =
| WhereTyparIsValueType of
typar: SynTypar *
range: range
| WhereTyparIsValueType of typar: SynTypar * range: range
| WhereTyparIsReferenceType of
typar: SynTypar *
range: range
| WhereTyparIsReferenceType of typar: SynTypar * range: range
| WhereTyparIsUnmanaged of
typar: SynTypar *
range: range
| WhereTyparIsUnmanaged of typar: SynTypar * range: range
| WhereTyparSupportsNull of
typar: SynTypar *
range: range
| WhereTyparSupportsNull of typar: SynTypar * range: range
| WhereTyparIsComparable of
typar: SynTypar *
range: range
| WhereTyparIsComparable of typar: SynTypar * range: range
| WhereTyparIsEquatable of
typar: SynTypar *
range: range
| WhereTyparIsEquatable of typar: SynTypar * range: range
| WhereTyparDefaultsToType of
typar: SynTypar *
typeName: SynType *
range: range
| WhereTyparDefaultsToType of typar: SynTypar * typeName: SynType * range: range
| WhereTyparSubtypeOfType of
typar: SynTypar *
typeName: SynType *
range: range
| WhereTyparSubtypeOfType of typar: SynTypar * typeName: SynType * range: range
| WhereTyparSupportsMember of
typars: SynType list *
memberSig: SynMemberSig *
range: range
| WhereTyparSupportsMember of typars: SynType list * memberSig: SynMemberSig * range: range
| WhereTyparIsEnum of
typar: SynTypar *
typeArgs: SynType list *
range: range
| WhereTyparIsEnum of typar: SynTypar * typeArgs: SynType list * range: range
| WhereTyparIsDelegate of
typar: SynTypar *
typeArgs: SynType list *
range: range
| WhereTyparIsDelegate of typar: SynTypar * typeArgs: SynType list * range: range
member x.Range =
match x with
| WhereTyparIsValueType(range=range)
| WhereTyparIsReferenceType(range=range)
| WhereTyparIsUnmanaged(range=range)
| WhereTyparSupportsNull(range=range)
| WhereTyparIsComparable(range=range)
| WhereTyparIsEquatable(range=range)
| WhereTyparDefaultsToType(range=range)
| WhereTyparSubtypeOfType(range=range)
| WhereTyparSupportsMember(range=range)
| WhereTyparIsEnum(range=range)
| WhereTyparIsDelegate(range=range) -> range
| WhereTyparIsValueType (range = range)
| WhereTyparIsReferenceType (range = range)
| WhereTyparIsUnmanaged (range = range)
| WhereTyparSupportsNull (range = range)
| WhereTyparIsComparable (range = range)
| WhereTyparIsEquatable (range = range)
| WhereTyparDefaultsToType (range = range)
| WhereTyparSubtypeOfType (range = range)
| WhereTyparSupportsMember (range = range)
| WhereTyparIsEnum (range = range)
| WhereTyparIsDelegate (range = range) -> range
[<RequireQualifiedAccess>]
type SynTyparDecls =
......@@ -367,32 +348,31 @@ type SynTyparDecls =
member x.TyparDecls =
match x with
| PostfixList (decls=decls)
| PrefixList (decls=decls) -> decls
| SinglePrefix (decl, _) -> [decl]
| PostfixList (decls = decls)
| PrefixList (decls = decls) -> decls
| SinglePrefix (decl, _) -> [ decl ]
member x.Constraints =
match x with
| PostfixList (constraints=constraints) -> constraints
| PostfixList (constraints = constraints) -> constraints
| _ -> []
member x.Range =
match x with
| PostfixList (range=range)
| PrefixList (range=range) -> range
| SinglePrefix (range=range) -> range
| PostfixList (range = range)
| PrefixList (range = range) -> range
| SinglePrefix (range = range) -> range
[<NoEquality; NoComparison;RequireQualifiedAccess>]
type SynType =
| LongIdent of
longDotId: SynLongIdent
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynType =
| LongIdent of longDotId: SynLongIdent
| App of
typeName: SynType *
lessRange: range option *
typeArgs: SynType list *
commaRanges: range list * // interstitial commas
commaRanges: range list * // interstitial commas
greaterRange: range option *
isPostfix: bool *
range: range
......@@ -402,149 +382,94 @@ type SynType =
longDotId: SynLongIdent *
lessRange: range option *
typeArgs: SynType list *
commaRanges: range list * // interstitial commas
commaRanges: range list * // interstitial commas
greaterRange: range option *
range: range
| Tuple of
isStruct: bool *
elementTypes:(bool*SynType) list *
range: range
| Tuple of isStruct: bool * elementTypes: (bool * SynType) list * range: range
| AnonRecd of
isStruct: bool *
fields:(Ident * SynType) list *
range: range
| AnonRecd of isStruct: bool * fields: (Ident * SynType) list * range: range
| Array of
rank: int *
elementType: SynType *
range: range
| Array of rank: int * elementType: SynType * range: range
| Fun of
argType: SynType *
returnType: SynType *
range: range
| Fun of argType: SynType * returnType: SynType * range: range
| Var of
typar: SynTypar *
range: range
| Var of typar: SynTypar * range: range
| Anon of range: range
| WithGlobalConstraints of
typeName: SynType *
constraints: SynTypeConstraint list *
range: range
| WithGlobalConstraints of typeName: SynType * constraints: SynTypeConstraint list * range: range
| HashConstraint of
innerType: SynType *
range: range
| HashConstraint of innerType: SynType * range: range
| MeasureDivide of
dividend: SynType *
divisor: SynType *
range: range
| MeasureDivide of dividend: SynType * divisor: SynType * range: range
| MeasurePower of
baseMeasure: SynType *
exponent: SynRationalConst *
range: range
| MeasurePower of baseMeasure: SynType * exponent: SynRationalConst * range: range
| StaticConstant of
constant: SynConst *
range: range
| StaticConstant of constant: SynConst * range: range
| StaticConstantExpr of
expr: SynExpr *
range: range
| StaticConstantExpr of expr: SynExpr * range: range
| StaticConstantNamed of
ident: SynType *
value: SynType *
range: range
| StaticConstantNamed of ident: SynType * value: SynType * range: range
| Paren of
innerType: SynType *
range: range
| Paren of innerType: SynType * range: range
member x.Range =
match x with
| SynType.App (range=m)
| SynType.LongIdentApp (range=m)
| SynType.Tuple (range=m)
| SynType.Array (range=m)
| SynType.AnonRecd (range=m)
| SynType.Fun (range=m)
| SynType.Var (range=m)
| SynType.Anon (range=m)
| SynType.WithGlobalConstraints (range=m)
| SynType.StaticConstant (range=m)
| SynType.StaticConstantExpr (range=m)
| SynType.StaticConstantNamed (range=m)
| SynType.HashConstraint (range=m)
| SynType.MeasureDivide (range=m)
| SynType.MeasurePower (range=m)
| SynType.Paren (range=m) -> m
| SynType.App (range = m)
| SynType.LongIdentApp (range = m)
| SynType.Tuple (range = m)
| SynType.Array (range = m)
| SynType.AnonRecd (range = m)
| SynType.Fun (range = m)
| SynType.Var (range = m)
| SynType.Anon (range = m)
| SynType.WithGlobalConstraints (range = m)
| SynType.StaticConstant (range = m)
| SynType.StaticConstantExpr (range = m)
| SynType.StaticConstantNamed (range = m)
| SynType.HashConstraint (range = m)
| SynType.MeasureDivide (range = m)
| SynType.MeasurePower (range = m)
| SynType.Paren (range = m) -> m
| SynType.LongIdent lidwd -> lidwd.Range
[<NoEquality; NoComparison;RequireQualifiedAccess>]
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynExpr =
| Paren of
expr: SynExpr *
leftParenRange: range *
rightParenRange: range option *
range: range
| Paren of expr: SynExpr * leftParenRange: range * rightParenRange: range option * range: range
| Quote of
operator: SynExpr *
isRaw: bool *
quotedExpr: SynExpr *
isFromQueryExpression: bool *
range: range
| Quote of operator: SynExpr * isRaw: bool * quotedExpr: SynExpr * isFromQueryExpression: bool * range: range
| Const of
constant: SynConst *
range: range
| Const of constant: SynConst * range: range
| Typed of
expr: SynExpr *
targetType: SynType *
range: range
| Typed of expr: SynExpr * targetType: SynType * range: range
| Tuple of
isStruct: bool *
exprs: SynExpr list *
commaRanges: range list * // interstitial commas
range: range
commaRanges: range list * // interstitial commas
range: range
| AnonRecd of
isStruct: bool *
copyInfo:(SynExpr * BlockSeparator) option *
recordFields:(Ident * range option * SynExpr) list *
copyInfo: (SynExpr * BlockSeparator) option *
recordFields: (Ident * range option * SynExpr) list *
range: range
| ArrayOrList of
isArray: bool *
exprs: SynExpr list *
range: range
| ArrayOrList of isArray: bool * exprs: SynExpr list * range: range
| Record of
baseInfo:(SynType * SynExpr * range * BlockSeparator option * range) option *
copyInfo:(SynExpr * BlockSeparator) option *
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
| New of isProtected: bool * targetType: SynType * expr: SynExpr * range: range
| ObjExpr of
objType: SynType *
argOptions:(SynExpr * Ident option) option *
argOptions: (SynExpr * Ident option) option *
withKeyword: range option *
bindings: SynBinding list *
members: SynMemberDefn list *
......@@ -552,11 +477,7 @@ type SynExpr =
newExprRange: range *
range: range
| While of
whileDebugPoint: DebugPointAtWhile *
whileExpr: SynExpr *
doExpr: SynExpr *
range: range
| While of whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range
| For of
forDebugPoint: DebugPointAtFor *
......@@ -579,27 +500,13 @@ type SynExpr =
bodyExpr: SynExpr *
range: range
| ArrayOrListComputed of
isArray: bool *
expr: SynExpr *
range: range
| ArrayOrListComputed of isArray: bool * expr: SynExpr * range: range
| IndexRange of
expr1: SynExpr option *
opm: range *
expr2: SynExpr option*
range1: range *
range2: range *
range: range
| IndexRange of expr1: SynExpr option * opm: range * expr2: SynExpr option * range1: range * range2: range * range: range
| IndexFromEnd of
expr: SynExpr *
range: range
| IndexFromEnd of expr: SynExpr * range: range
| ComputationExpr of
hasSeqBuilder: bool *
expr: SynExpr *
range: range
| ComputationExpr of hasSeqBuilder: bool * expr: SynExpr * range: range
| Lambda of
fromMethod: bool *
......@@ -624,20 +531,11 @@ type SynExpr =
range: range *
trivia: SynExprMatchTrivia
| Do of
expr: SynExpr *
range: range
| Do of expr: SynExpr * range: range
| Assert of
expr: SynExpr *
range: range
| Assert of expr: SynExpr * range: range
| App of
flag: ExprAtomicFlag *
isInfix: bool *
funcExpr: SynExpr *
argExpr: SynExpr *
range: range
| App of flag: ExprAtomicFlag * isInfix: bool * funcExpr: SynExpr * argExpr: SynExpr * range: range
| TypeApp of
expr: SynExpr *
......@@ -648,13 +546,7 @@ type SynExpr =
typeArgsRange: range *
range: range
| LetOrUse of
isRecursive: bool *
isUse: bool *
bindings: SynBinding list *
body: SynExpr *
range: range *
trivia: SynExprLetOrUseTrivia
| LetOrUse of isRecursive: bool * isUse: bool * bindings: SynBinding list * body: SynExpr * range: range * trivia: SynExprLetOrUseTrivia
| TryWith of
tryExpr: SynExpr *
......@@ -672,16 +564,9 @@ type SynExpr =
finallyDebugPoint: DebugPointAtFinally *
trivia: SynExprTryFinallyTrivia
| Lazy of
expr: SynExpr *
range: range
| Lazy of expr: SynExpr * range: range
| Sequential of
debugPoint: DebugPointAtSequential *
isTrueSeq: bool *
expr1: SynExpr *
expr2: SynExpr *
range: range
| Sequential of debugPoint: DebugPointAtSequential * isTrueSeq: bool * expr1: SynExpr * expr2: SynExpr * range: range
| IfThenElse of
ifExpr: SynExpr *
......@@ -692,42 +577,19 @@ type SynExpr =
range: range *
trivia: SynExprIfThenElseTrivia
| Ident of
ident: Ident
| Ident of ident: Ident
| LongIdent of
isOptional: bool *
longDotId: SynLongIdent *
altNameRefCell: SynSimplePatAlternativeIdInfo ref option *
range: range
| LongIdent of isOptional: bool * longDotId: SynLongIdent * altNameRefCell: SynSimplePatAlternativeIdInfo ref option * range: range
| LongIdentSet of
longDotId: SynLongIdent *
expr: SynExpr *
range: range
| LongIdentSet of longDotId: SynLongIdent * expr: SynExpr * range: range
| DotGet of
expr: SynExpr *
rangeOfDot: range *
longDotId: SynLongIdent *
range: range
| DotGet of expr: SynExpr * rangeOfDot: range * longDotId: SynLongIdent * range: range
| DotSet of
targetExpr: SynExpr *
longDotId: SynLongIdent *
rhsExpr: SynExpr *
range: range
| DotSet of targetExpr: SynExpr * longDotId: SynLongIdent * rhsExpr: SynExpr * range: range
| Set of
targetExpr: SynExpr *
rhsExpr: SynExpr *
range: range
| Set of targetExpr: SynExpr * rhsExpr: SynExpr * range: range
| DotIndexedGet of
objectExpr: SynExpr *
indexArgs: SynExpr *
dotRange: range *
range: range
| DotIndexedGet of objectExpr: SynExpr * indexArgs: SynExpr * dotRange: range * range: range
| DotIndexedSet of
objectExpr: SynExpr *
......@@ -737,82 +599,35 @@ type SynExpr =
dotRange: range *
range: range
| NamedIndexedPropertySet of
longDotId: SynLongIdent *
expr1: SynExpr *
expr2: SynExpr *
range: range
| NamedIndexedPropertySet of longDotId: SynLongIdent * expr1: SynExpr * expr2: SynExpr * range: range
| DotNamedIndexedPropertySet of
targetExpr: SynExpr *
longDotId: SynLongIdent *
argExpr: SynExpr *
rhsExpr: SynExpr *
range: range
| DotNamedIndexedPropertySet of targetExpr: SynExpr * longDotId: SynLongIdent * argExpr: SynExpr * rhsExpr: SynExpr * range: range
| TypeTest of
expr: SynExpr *
targetType: SynType *
range: range
| TypeTest of expr: SynExpr * targetType: SynType * range: range
| Upcast of
expr: SynExpr *
targetType: SynType *
range: range
| Upcast of expr: SynExpr * targetType: SynType * range: range
| Downcast of
expr: SynExpr *
targetType: SynType *
range: range
| Downcast of expr: SynExpr * targetType: SynType * range: range
| InferredUpcast of
expr: SynExpr *
range: range
| InferredUpcast of expr: SynExpr * range: range
| InferredDowncast of
expr: SynExpr *
range: range
| InferredDowncast of expr: SynExpr * range: range
| Null of
range: range
| Null of range: range
| AddressOf of
isByref: bool *
expr: SynExpr *
opRange: range *
range: range
| AddressOf of isByref: bool * expr: SynExpr * opRange: range * range: range
| TraitCall of
supportTys: SynTypar list *
traitSig: SynMemberSig *
argExpr: SynExpr *
range: range
| TraitCall of supportTys: SynTypar list * traitSig: SynMemberSig * argExpr: SynExpr * range: range
| JoinIn of
lhsExpr: SynExpr *
lhsRange: range *
rhsExpr: SynExpr *
range: range
| JoinIn of lhsExpr: SynExpr * lhsRange: range * rhsExpr: SynExpr * range: range
| ImplicitZero of
range: range
| ImplicitZero of range: range
| SequentialOrImplicitYield of
debugPoint:DebugPointAtSequential *
expr1:SynExpr *
expr2:SynExpr *
ifNotStmt:SynExpr *
range:range
| SequentialOrImplicitYield of debugPoint: DebugPointAtSequential * expr1: SynExpr * expr2: SynExpr * ifNotStmt: SynExpr * range: range
| YieldOrReturn of
flags: (bool * bool) *
expr: SynExpr *
range: range
| YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range
| YieldOrReturnFrom of
flags: (bool * bool) *
expr: SynExpr *
range: range
| YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range
| LetOrUseBang of
bindDebugPoint: DebugPointAtBinding *
......@@ -821,7 +636,7 @@ type SynExpr =
pat: SynPat *
rhs: SynExpr *
andBangs: SynExprAndBang list *
body:SynExpr *
body: SynExpr *
range: range *
trivia: SynExprLetOrUseBangTrivia
......@@ -832,12 +647,10 @@ type SynExpr =
range: range *
trivia: SynExprMatchBangTrivia
| DoBang of
expr: SynExpr *
range: range
| DoBang of expr: SynExpr * range: range
| LibraryOnlyILAssembly of
ilCode: obj * // this type is ILInstr[] but is hidden to avoid the representation of AbstractIL being public
ilCode: obj * // this type is ILInstr[] but is hidden to avoid the representation of AbstractIL being public
typeArgs: SynType list *
args: SynExpr list *
retTy: SynType list *
......@@ -849,117 +662,94 @@ type SynExpr =
optimizedExpr: SynExpr *
range: range
| LibraryOnlyUnionCaseFieldGet of
expr: SynExpr *
longId: LongIdent *
fieldNum: int *
range: range
| LibraryOnlyUnionCaseFieldGet of expr: SynExpr * longId: LongIdent * fieldNum: int * range: range
| LibraryOnlyUnionCaseFieldSet of
expr: SynExpr *
longId: LongIdent *
fieldNum: int *
rhsExpr: SynExpr *
range: range
| LibraryOnlyUnionCaseFieldSet of expr: SynExpr * longId: LongIdent * fieldNum: int * rhsExpr: SynExpr * range: range
| ArbitraryAfterError of
debugStr: string *
range: range
| ArbitraryAfterError of debugStr: string * range: range
| FromParseError of
expr: SynExpr *
range: range
| FromParseError of expr: SynExpr * range: range
| DiscardAfterMissingQualificationAfterDot of
expr: SynExpr *
range: range
| DiscardAfterMissingQualificationAfterDot of expr: SynExpr * range: range
| Fixed of
expr: SynExpr *
range: range
| Fixed of expr: SynExpr * range: range
| InterpolatedString of
contents: SynInterpolatedStringPart list *
synStringKind :SynStringKind *
range: range
| InterpolatedString of contents: SynInterpolatedStringPart list * synStringKind: SynStringKind * range: range
| DebugPoint of
debugPoint: DebugPointAtLeafExpr *
isControlFlow: bool *
innerExpr: SynExpr
| DebugPoint of debugPoint: DebugPointAtLeafExpr * isControlFlow: bool * innerExpr: SynExpr
| Dynamic of funcExpr: SynExpr * qmark: range * argExpr: SynExpr * range: range
member e.Range =
match e with
| SynExpr.Paren (_, leftParenRange, rightParenRange, r) ->
match rightParenRange with
| Some rightParenRange when leftParenRange.FileIndex <> rightParenRange.FileIndex -> leftParenRange
| _ -> r
| SynExpr.Quote (range=m)
| SynExpr.Const (range=m)
| SynExpr.Typed (range=m)
| SynExpr.Tuple (range=m)
| SynExpr.AnonRecd (range=m)
| SynExpr.ArrayOrList (range=m)
| SynExpr.Record (range=m)
| SynExpr.New (range=m)
| SynExpr.ObjExpr (range=m)
| SynExpr.While (range=m)
| SynExpr.For (range=m)
| SynExpr.ForEach (range=m)
| SynExpr.ComputationExpr (range=m)
| SynExpr.ArrayOrListComputed (range=m)
| SynExpr.Lambda (range=m)
| SynExpr.Match (range=m)
| SynExpr.MatchLambda (range=m)
| SynExpr.Do (range=m)
| SynExpr.Assert (range=m)
| SynExpr.App (range=m)
| SynExpr.TypeApp (range=m)
| SynExpr.LetOrUse (range=m)
| SynExpr.TryWith (range=m)
| SynExpr.TryFinally (range=m)
| SynExpr.Sequential (range=m)
| SynExpr.SequentialOrImplicitYield (range=m)
| SynExpr.ArbitraryAfterError (range=m)
| SynExpr.FromParseError (range=m)
| SynExpr.DiscardAfterMissingQualificationAfterDot (range=m)
| SynExpr.IfThenElse (range=m)
| SynExpr.LongIdent (range=m)
| SynExpr.LongIdentSet (range=m)
| SynExpr.NamedIndexedPropertySet (range=m)
| SynExpr.DotIndexedGet (range=m)
| SynExpr.DotIndexedSet (range=m)
| SynExpr.DotGet (range=m)
| SynExpr.DotSet (range=m)
| SynExpr.Set (range=m)
| SynExpr.DotNamedIndexedPropertySet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldSet (range=m)
| SynExpr.LibraryOnlyILAssembly (range=m)
| SynExpr.LibraryOnlyStaticOptimization (range=m)
| SynExpr.IndexRange (range=m)
| SynExpr.IndexFromEnd (range=m)
| SynExpr.TypeTest (range=m)
| SynExpr.Upcast (range=m)
| SynExpr.AddressOf (range=m)
| SynExpr.Downcast (range=m)
| SynExpr.JoinIn (range=m)
| SynExpr.InferredUpcast (range=m)
| SynExpr.InferredDowncast (range=m)
| SynExpr.Null (range=m)
| SynExpr.Lazy (range=m)
| SynExpr.TraitCall (range=m)
| SynExpr.ImplicitZero (range=m)
| SynExpr.YieldOrReturn (range=m)
| SynExpr.YieldOrReturnFrom (range=m)
| SynExpr.LetOrUseBang (range=m)
| SynExpr.MatchBang (range=m)
| SynExpr.DoBang (range=m)
| SynExpr.Fixed (range=m)
| SynExpr.InterpolatedString (range=m)
| SynExpr.Dynamic(range=m) -> m
| SynExpr.Quote (range = m)
| SynExpr.Const (range = m)
| SynExpr.Typed (range = m)
| SynExpr.Tuple (range = m)
| SynExpr.AnonRecd (range = m)
| SynExpr.ArrayOrList (range = m)
| SynExpr.Record (range = m)
| SynExpr.New (range = m)
| SynExpr.ObjExpr (range = m)
| SynExpr.While (range = m)
| SynExpr.For (range = m)
| SynExpr.ForEach (range = m)
| SynExpr.ComputationExpr (range = m)
| SynExpr.ArrayOrListComputed (range = m)
| SynExpr.Lambda (range = m)
| SynExpr.Match (range = m)
| SynExpr.MatchLambda (range = m)
| SynExpr.Do (range = m)
| SynExpr.Assert (range = m)
| SynExpr.App (range = m)
| SynExpr.TypeApp (range = m)
| SynExpr.LetOrUse (range = m)
| SynExpr.TryWith (range = m)
| SynExpr.TryFinally (range = m)
| SynExpr.Sequential (range = m)
| SynExpr.SequentialOrImplicitYield (range = m)
| SynExpr.ArbitraryAfterError (range = m)
| SynExpr.FromParseError (range = m)
| SynExpr.DiscardAfterMissingQualificationAfterDot (range = m)
| SynExpr.IfThenElse (range = m)
| SynExpr.LongIdent (range = m)
| SynExpr.LongIdentSet (range = m)
| SynExpr.NamedIndexedPropertySet (range = m)
| SynExpr.DotIndexedGet (range = m)
| SynExpr.DotIndexedSet (range = m)
| SynExpr.DotGet (range = m)
| SynExpr.DotSet (range = m)
| SynExpr.Set (range = m)
| SynExpr.DotNamedIndexedPropertySet (range = m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (range = m)
| SynExpr.LibraryOnlyUnionCaseFieldSet (range = m)
| SynExpr.LibraryOnlyILAssembly (range = m)
| SynExpr.LibraryOnlyStaticOptimization (range = m)
| SynExpr.IndexRange (range = m)
| SynExpr.IndexFromEnd (range = m)
| SynExpr.TypeTest (range = m)
| SynExpr.Upcast (range = m)
| SynExpr.AddressOf (range = m)
| SynExpr.Downcast (range = m)
| SynExpr.JoinIn (range = m)
| SynExpr.InferredUpcast (range = m)
| SynExpr.InferredDowncast (range = m)
| SynExpr.Null (range = m)
| SynExpr.Lazy (range = m)
| SynExpr.TraitCall (range = m)
| SynExpr.ImplicitZero (range = m)
| SynExpr.YieldOrReturn (range = m)
| SynExpr.YieldOrReturnFrom (range = m)
| SynExpr.LetOrUseBang (range = m)
| SynExpr.MatchBang (range = m)
| SynExpr.DoBang (range = m)
| SynExpr.Fixed (range = m)
| SynExpr.InterpolatedString (range = m)
| SynExpr.Dynamic (range = m) -> m
| SynExpr.Ident id -> id.idRange
| SynExpr.DebugPoint (_, _, innerExpr) -> innerExpr.Range
......@@ -980,9 +770,8 @@ type SynExpr =
| SynExpr.Paren (_, m, _, _) -> m
| SynExpr.Sequential (_, _, e1, _, _)
| SynExpr.SequentialOrImplicitYield (_, e1, _, _, _)
| SynExpr.App (_, _, e1, _, _) ->
e1.RangeOfFirstPortion
| SynExpr.ForEach (pat=pat; range=r) ->
| SynExpr.App (_, _, e1, _, _) -> e1.RangeOfFirstPortion
| SynExpr.ForEach (pat = pat; range = r) ->
let start = r.Start
let e = (pat.Range: range).Start
mkRange r.FileName start e
......@@ -1027,21 +816,15 @@ type SynSimplePat =
isOptional: bool *
range: range
| Typed of
pat: SynSimplePat *
targetType: SynType *
range: range
| Typed of pat: SynSimplePat * targetType: SynType * range: range
| Attrib of
pat: SynSimplePat *
attributes: SynAttributes *
range: range
| Attrib of pat: SynSimplePat * attributes: SynAttributes * range: range
member x.Range =
match x with
| SynSimplePat.Id(range=range)
| SynSimplePat.Typed(range=range)
| SynSimplePat.Attrib(range=range) -> range
| SynSimplePat.Id (range = range)
| SynSimplePat.Typed (range = range)
| SynSimplePat.Attrib (range = range) -> range
[<RequireQualifiedAccess>]
type SynSimplePatAlternativeIdInfo =
......@@ -1053,173 +836,116 @@ type SynSimplePatAlternativeIdInfo =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynStaticOptimizationConstraint =
| WhenTyparTyconEqualsTycon of
typar: SynTypar *
rhsType: SynType *
range: range
| WhenTyparTyconEqualsTycon of typar: SynTypar * rhsType: SynType * range: range
| WhenTyparIsStruct of
typar: SynTypar *
range: range
| WhenTyparIsStruct of typar: SynTypar * range: range
[<NoEquality; NoComparison;RequireQualifiedAccess>]
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynSimplePats =
| SimplePats of
pats: SynSimplePat list *
range: range
| SimplePats of pats: SynSimplePat list * range: range
| Typed of
pats: SynSimplePats *
targetType: SynType *
range: range
| Typed of pats: SynSimplePats * targetType: SynType * range: range
member x.Range =
match x with
| SynSimplePats.SimplePats(range=range)
| SynSimplePats.Typed(range=range) -> range
| SynSimplePats.SimplePats (range = range)
| SynSimplePats.Typed (range = range) -> range
[<RequireQualifiedAccess>]
type SynArgPats =
| Pats of
pats: SynPat list
| Pats of pats: SynPat list
| NamePatPairs of
pats: (Ident * range * SynPat) list *
range: range
| NamePatPairs of pats: (Ident * range * SynPat) list * range: range
member x.Patterns =
match x with
| Pats pats -> pats
| NamePatPairs (pats, _) -> pats |> List.map (fun (_,_, pat) -> pat)
| NamePatPairs (pats, _) -> pats |> List.map (fun (_, _, pat) -> pat)
[<NoEquality; NoComparison;RequireQualifiedAccess>]
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynPat =
| Const of
constant: SynConst *
range: range
| Const of constant: SynConst * range: range
| Wild of
range: range
| Wild of range: range
| Named of
ident: SynIdent *
isThisVal: bool *
accessibility: SynAccess option *
range: range
| Named of ident: SynIdent * isThisVal: bool * accessibility: SynAccess option * range: range
| Typed of
pat: SynPat *
targetType: SynType *
range: range
| Typed of pat: SynPat * targetType: SynType * range: range
| Attrib of
pat: SynPat *
attributes: SynAttributes *
range: range
| Attrib of pat: SynPat * attributes: SynAttributes * range: range
| Or of
lhsPat: SynPat *
rhsPat: SynPat *
range: range *
trivia: SynPatOrTrivia
| Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia
| Ands of
pats: SynPat list *
range: range
| As of
lhsPat: SynPat *
rhsPat: SynPat *
range: range
| Ands of pats: SynPat list * range: range
| As of lhsPat: SynPat * rhsPat: SynPat * range: range
| LongIdent of
longDotId: SynLongIdent *
propertyKeyword: PropertyKeyword option *
extraId: Ident option * // holds additional ident for tooling
typarDecls: SynValTyparDecls option * // usually None: temporary used to parse "f<'a> x = x"
extraId: Ident option * // holds additional ident for tooling
typarDecls: SynValTyparDecls option * // usually None: temporary used to parse "f<'a> x = x"
argPats: SynArgPats *
accessibility: SynAccess option *
range: range
| Tuple of
isStruct: bool *
elementPats: SynPat list *
range: range
| Tuple of isStruct: bool * elementPats: SynPat list * range: range
| Paren of
pat: SynPat *
range: range
| Paren of pat: SynPat * range: range
| ArrayOrList of
isArray: bool *
elementPats: SynPat list *
range: range
| ArrayOrList of isArray: bool * elementPats: SynPat list * range: range
| Record of
fieldPats: ((LongIdent * Ident) * range * SynPat) list *
range: range
| Record of fieldPats: ((LongIdent * Ident) * range * SynPat) list * range: range
| Null of
range: range
| Null of range: range
| OptionalVal of
ident: Ident *
range: range
| OptionalVal of ident: Ident * range: range
| IsInst of
pat: SynType *
range: range
| IsInst of pat: SynType * range: range
| QuoteExpr of
expr: SynExpr *
range: range
| QuoteExpr of expr: SynExpr * range: range
| DeprecatedCharRange of
startChar: char *
endChar: char *
range: range
| DeprecatedCharRange of startChar: char * endChar: char * range: range
| InstanceMember of
thisId: Ident *
memberId: Ident *
toolingId: Ident option * // holds additional ident for tooling
toolingId: Ident option * // holds additional ident for tooling
accessibility: SynAccess option *
range: range
| FromParseError of
pat: SynPat *
range: range
| FromParseError of pat: SynPat * range: range
member p.Range =
match p with
| SynPat.Const (range=m)
| SynPat.Wild (range=m)
| SynPat.Named (range=m)
| SynPat.Or (range=m)
| SynPat.Ands (range=m)
| SynPat.As (range=m)
| SynPat.LongIdent (range=m)
| SynPat.ArrayOrList (range=m)
| SynPat.Tuple (range=m)
| SynPat.Typed (range=m)
| SynPat.Attrib (range=m)
| SynPat.Record (range=m)
| SynPat.DeprecatedCharRange (range=m)
| SynPat.Null (range=m)
| SynPat.IsInst (range=m)
| SynPat.QuoteExpr (range=m)
| SynPat.InstanceMember (range=m)
| SynPat.OptionalVal (range=m)
| SynPat.Paren (range=m)
| SynPat.FromParseError (range=m) -> m
match p with
| SynPat.Const (range = m)
| SynPat.Wild (range = m)
| SynPat.Named (range = m)
| SynPat.Or (range = m)
| SynPat.Ands (range = m)
| SynPat.As (range = m)
| SynPat.LongIdent (range = m)
| SynPat.ArrayOrList (range = m)
| SynPat.Tuple (range = m)
| SynPat.Typed (range = m)
| SynPat.Attrib (range = m)
| SynPat.Record (range = m)
| SynPat.DeprecatedCharRange (range = m)
| SynPat.Null (range = m)
| SynPat.IsInst (range = m)
| SynPat.QuoteExpr (range = m)
| SynPat.InstanceMember (range = m)
| SynPat.OptionalVal (range = m)
| SynPat.Paren (range = m)
| SynPat.FromParseError (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type PropertyKeyword =
| With of range
| And of range
[<NoEquality; NoComparison;>]
[<NoEquality; NoComparison>]
type SynInterfaceImpl =
| SynInterfaceImpl of
interfaceTy: SynType *
......@@ -1240,46 +966,44 @@ type SynMatchClause =
member this.RangeOfGuardAndRhs =
match this with
| SynMatchClause(whenExpr=eo; resultExpr=e) ->
| SynMatchClause (whenExpr = eo; resultExpr = e) ->
match eo with
| None -> e.Range
| Some x -> unionRanges e.Range x.Range
member this.Range =
match this with
| SynMatchClause(range = m) -> m
| SynMatchClause (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynAttribute =
{ TypeName: SynLongIdent
{
TypeName: SynLongIdent
ArgExpr: SynExpr
ArgExpr: SynExpr
Target: Ident option
Target: Ident option
AppliesToGetterAndSetter: bool
AppliesToGetterAndSetter: bool
Range: range
Range: range
}
[<RequireQualifiedAccess>]
type SynAttributeList =
{
Attributes: SynAttribute list
Range: range
{
Attributes: SynAttribute list
Range: range
}
type SynAttributes = SynAttributeList list
[<NoEquality; NoComparison>]
type SynValData =
| SynValData of
memberFlags: SynMemberFlags option *
valInfo: SynValInfo *
thisIdOpt: Ident option
| SynValData of memberFlags: SynMemberFlags option * valInfo: SynValInfo * thisIdOpt: Ident option
member x.SynValInfo = (let (SynValData(_flags, synValInfo, _)) = x in synValInfo)
member x.SynValInfo = (let (SynValData (_flags, synValInfo, _)) = x in synValInfo)
[<NoEquality; NoComparison>]
type SynBinding =
......@@ -1293,7 +1017,7 @@ type SynBinding =
valData: SynValData *
headPat: SynPat *
returnInfo: SynBindingReturnInfo option *
expr: SynExpr *
expr: SynExpr *
range: range *
debugPoint: DebugPointAtBinding *
trivia: SynBindingTrivia
......@@ -1302,35 +1026,32 @@ type SynBinding =
// - for everything else, the 'range' member that appears last/second-to-last is the 'full range' of the whole tree construct
// - but for Binding, the 'range' is only the range of the left-hand-side, the right-hand-side range is in the SynExpr
// - so we use explicit names to avoid confusion
member x.RangeOfBindingWithoutRhs = let (SynBinding(range=m)) = x in m
member x.RangeOfBindingWithoutRhs = let (SynBinding (range = m)) = x in m
member x.RangeOfBindingWithRhs = let (SynBinding(expr=e; range=m)) = x in unionRanges e.Range m
member x.RangeOfBindingWithRhs =
let (SynBinding (expr = e; range = m)) = x in unionRanges e.Range m
member x.RangeOfHeadPattern = let (SynBinding(headPat=headPat)) = x in headPat.Range
member x.RangeOfHeadPattern = let (SynBinding (headPat = headPat)) = x in headPat.Range
[<NoEquality; NoComparison>]
type SynBindingReturnInfo =
| SynBindingReturnInfo of
typeName: SynType *
range: range *
attributes: SynAttributes
type SynBindingReturnInfo = SynBindingReturnInfo of typeName: SynType * range: range * attributes: SynAttributes
[<NoComparison; RequireQualifiedAccess; CustomEquality>]
type SynMemberFlags =
{
IsInstance: bool
{
IsInstance: bool
IsDispatchSlot: bool
IsDispatchSlot: bool
IsOverrideOrExplicitImpl: bool
IsOverrideOrExplicitImpl: bool
IsFinal: bool
IsFinal: bool
MemberKind: SynMemberKind
MemberKind: SynMemberKind
Trivia: SynMemberFlagsTrivia
Trivia: SynMemberFlagsTrivia
}
override this.Equals other =
match other with
| :? SynMemberFlags as other ->
......@@ -1341,12 +1062,12 @@ type SynMemberFlags =
&& this.MemberKind = other.MemberKind
| _ -> false
override this.GetHashCode () =
hash this.IsInstance +
hash this.IsDispatchSlot +
hash this.IsOverrideOrExplicitImpl +
hash this.IsFinal +
hash this.MemberKind
override this.GetHashCode() =
hash this.IsInstance
+ hash this.IsDispatchSlot
+ hash this.IsOverrideOrExplicitImpl
+ hash this.IsFinal
+ hash this.MemberKind
[<StructuralEquality; NoComparison; RequireQualifiedAccess>]
type SynMemberKind =
......@@ -1366,34 +1087,23 @@ type SynMemberKind =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynMemberSig =
| Member of
memberSig: SynValSig *
flags: SynMemberFlags *
range: range
| Member of memberSig: SynValSig * flags: SynMemberFlags * range: range
| Interface of
interfaceType: SynType *
range: range
| Interface of interfaceType: SynType * range: range
| Inherit of
inheritedType: SynType *
range: range
| Inherit of inheritedType: SynType * range: range
| ValField of
field: SynField *
range: range
| ValField of field: SynField * range: range
| NestedType of
nestedType: SynTypeDefnSig *
range: range
| NestedType of nestedType: SynTypeDefnSig * range: range
member d.Range =
match d with
| SynMemberSig.Member (range=m)
| SynMemberSig.Interface (range=m)
| SynMemberSig.Inherit (range=m)
| SynMemberSig.ValField (range=m)
| SynMemberSig.NestedType (range=m) -> m
| SynMemberSig.Member (range = m)
| SynMemberSig.Interface (range = m)
| SynMemberSig.Inherit (range = m)
| SynMemberSig.ValField (range = m)
| SynMemberSig.NestedType (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynTypeDefnKind =
......@@ -1412,19 +1122,11 @@ type SynTypeDefnKind =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynTypeDefnSimpleRepr =
| Union of
accessibility: SynAccess option *
unionCases: SynUnionCase list *
range: range
| Union of accessibility: SynAccess option * unionCases: SynUnionCase list * range: range
| Enum of
cases: SynEnumCase list *
range: range
| Enum of cases: SynEnumCase list * range: range
| Record of
accessibility: SynAccess option *
recordFields: SynField list *
range: range
| Record of accessibility: SynAccess option * recordFields: SynField list * range: range
| General of
kind: SynTypeDefnKind *
......@@ -1437,29 +1139,24 @@ type SynTypeDefnSimpleRepr =
range: range
| LibraryOnlyILAssembly of
ilType: obj * // this type is ILType but is hidden to avoid the representation of AbstractIL being public
ilType: obj * // this type is ILType but is hidden to avoid the representation of AbstractIL being public
range: range
| TypeAbbrev of
detail: ParserDetail *
rhsType: SynType *
range: range
| TypeAbbrev of detail: ParserDetail * rhsType: SynType * range: range
| None of
range: range
| None of range: range
| Exception of
exnRepr: SynExceptionDefnRepr
| Exception of exnRepr: SynExceptionDefnRepr
member this.Range =
match this with
| Union (range=m)
| Enum (range=m)
| Record (range=m)
| General (range=m)
| LibraryOnlyILAssembly (range=m)
| TypeAbbrev (range=m)
| None (range=m) -> m
| Union (range = m)
| Enum (range = m)
| Record (range = m)
| General (range = m)
| LibraryOnlyILAssembly (range = m)
| TypeAbbrev (range = m)
| None (range = m) -> m
| Exception t -> t.Range
[<NoEquality; NoComparison>]
......@@ -1476,7 +1173,7 @@ type SynEnumCase =
member this.Range =
match this with
| SynEnumCase (range=m) -> m
| SynEnumCase (range = m) -> m
[<NoEquality; NoComparison>]
type SynUnionCase =
......@@ -1492,37 +1189,28 @@ type SynUnionCase =
member this.Range =
match this with
| SynUnionCase (range=m) -> m
| SynUnionCase (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynUnionCaseKind =
| Fields of
cases: SynField list
| Fields of cases: SynField list
| FullType of
fullType: SynType *
fullTypeInfo: SynValInfo
| FullType of fullType: SynType * fullTypeInfo: SynValInfo
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynTypeDefnSigRepr =
| ObjectModel of
kind: SynTypeDefnKind *
memberSigs: SynMemberSig list *
range: range
| ObjectModel of kind: SynTypeDefnKind * memberSigs: SynMemberSig list * range: range
| Simple of
repr: SynTypeDefnSimpleRepr *
range: range
| Simple of repr: SynTypeDefnSimpleRepr * range: range
| Exception of
repr: SynExceptionDefnRepr
| Exception of repr: SynExceptionDefnRepr
member this.Range =
match this with
| ObjectModel (range=m)
| Simple (range=m) -> m
| ObjectModel (range = m)
| Simple (range = m) -> m
| Exception e -> e.Range
[<NoEquality; NoComparison>]
......@@ -1538,7 +1226,7 @@ type SynTypeDefnSig =
member this.Range =
match this with
| SynTypeDefnSig(range=m) -> m
| SynTypeDefnSig (range = m) -> m
[<NoEquality; NoComparison>]
type SynField =
......@@ -1566,7 +1254,7 @@ type SynComponentInfo =
member this.Range =
match this with
| SynComponentInfo (range=m) -> m
| SynComponentInfo (range = m) -> m
[<NoEquality; NoComparison>]
type SynValSig =
......@@ -1584,47 +1272,40 @@ type SynValSig =
range: range *
trivia: SynValSigTrivia
member x.RangeOfId = let (SynValSig(ident=SynIdent(id, _))) = x in id.idRange
member x.RangeOfId = let (SynValSig(ident = SynIdent (id, _))) = x in id.idRange
member x.SynInfo = let (SynValSig(arity=v)) = x in v
member x.SynInfo = let (SynValSig (arity = v)) = x in v
member x.SynType = let (SynValSig(synType=ty)) = x in ty
member x.SynType = let (SynValSig (synType = ty)) = x in ty
[<NoEquality; NoComparison>]
type SynValInfo =
| SynValInfo of curriedArgInfos: SynArgInfo list list * returnInfo: SynArgInfo
member x.CurriedArgInfos = (let (SynValInfo(args, _)) = x in args)
member x.CurriedArgInfos = (let (SynValInfo (args, _)) = x in args)
member x.ArgNames =
x.CurriedArgInfos
|> List.concat
|> List.map (fun info -> info.Ident)
|> List.choose id
x.CurriedArgInfos
|> List.concat
|> List.map (fun info -> info.Ident)
|> List.choose id
|> List.map (fun id -> id.idText)
[<NoEquality; NoComparison>]
type SynArgInfo =
| SynArgInfo of
attributes: SynAttributes *
optional: bool *
ident: Ident option
| SynArgInfo of attributes: SynAttributes * optional: bool * ident: Ident option
member x.Ident : Ident option = let (SynArgInfo(_,_,id)) = x in id
member x.Ident: Ident option = let (SynArgInfo (_, _, id)) = x in id
member x.Attributes : SynAttributes = let (SynArgInfo(attrs,_,_)) = x in attrs
member x.Attributes: SynAttributes = let (SynArgInfo (attrs, _, _)) = x in attrs
[<NoEquality; NoComparison>]
type SynValTyparDecls =
| SynValTyparDecls of
typars: SynTyparDecls option *
canInfer: bool
type SynValTyparDecls = SynValTyparDecls of typars: SynTyparDecls option * canInfer: bool
[<NoEquality; NoComparison>]
type SynReturnInfo =
| SynReturnInfo of returnType: (SynType * SynArgInfo) * range: range
type SynReturnInfo = SynReturnInfo of returnType: (SynType * SynArgInfo) * range: range
[<NoEquality; NoComparison>]
type SynExceptionDefnRepr =
......@@ -1637,40 +1318,32 @@ type SynExceptionDefnRepr =
accessibility: SynAccess option *
range: range
member this.Range = match this with SynExceptionDefnRepr (range=m) -> m
member this.Range =
match this with
| SynExceptionDefnRepr (range = m) -> m
[<NoEquality; NoComparison>]
type SynExceptionDefn =
| SynExceptionDefn of
exnRepr: SynExceptionDefnRepr *
withKeyword: range option *
members: SynMemberDefns *
range: range
| SynExceptionDefn of exnRepr: SynExceptionDefnRepr * withKeyword: range option * members: SynMemberDefns * range: range
member this.Range =
match this with
| SynExceptionDefn (range=m) -> m
| SynExceptionDefn (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynTypeDefnRepr =
| ObjectModel of
kind: SynTypeDefnKind *
members: SynMemberDefns *
range: range
| ObjectModel of kind: SynTypeDefnKind * members: SynMemberDefns * range: range
| Simple of
simpleRepr: SynTypeDefnSimpleRepr *
range: range
| Simple of simpleRepr: SynTypeDefnSimpleRepr * range: range
| Exception of
exnRepr: SynExceptionDefnRepr
| Exception of exnRepr: SynExceptionDefnRepr
member this.Range =
match this with
| ObjectModel (range=m)
| Simple (range=m) -> m
| ObjectModel (range = m)
| Simple (range = m) -> m
| Exception t -> t.Range
[<NoEquality; NoComparison>]
......@@ -1685,18 +1358,14 @@ type SynTypeDefn =
member this.Range =
match this with
| SynTypeDefn (range=m) -> m
| SynTypeDefn (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynMemberDefn =
| Open of
target: SynOpenDeclTarget *
range: range
| Open of target: SynOpenDeclTarget * range: range
| Member of
memberDefn: SynBinding *
range: range
| Member of memberDefn: SynBinding * range: range
| ImplicitCtor of
accessibility: SynAccess option *
......@@ -1706,42 +1375,19 @@ type SynMemberDefn =
xmlDoc: PreXmlDoc *
range: range
| ImplicitInherit of
inheritType: SynType *
inheritArgs: SynExpr *
inheritAlias: Ident option *
range: range
| ImplicitInherit of inheritType: SynType * inheritArgs: SynExpr * inheritAlias: Ident option * range: range
| LetBindings of
bindings: SynBinding list *
isStatic: bool *
isRecursive: bool *
range: range
| LetBindings of bindings: SynBinding list * isStatic: bool * isRecursive: bool * range: range
| AbstractSlot of
slotSig: SynValSig *
flags: SynMemberFlags *
range: range
| AbstractSlot of slotSig: SynValSig * flags: SynMemberFlags * range: range
| Interface of
interfaceType: SynType *
withKeyword: range option *
members: SynMemberDefns option *
range: range
| Interface of interfaceType: SynType * withKeyword: range option * members: SynMemberDefns option * range: range
| Inherit of
baseType: SynType *
asIdent: Ident option *
range: range
| Inherit of baseType: SynType * asIdent: Ident option * range: range
| ValField of
fieldInfo: SynField *
range: range
| ValField of fieldInfo: SynField * range: range
| NestedType of
typeDefn: SynTypeDefn *
accessibility: SynAccess option *
range: range
| NestedType of typeDefn: SynTypeDefn * accessibility: SynAccess option * range: range
| AutoProperty of
attributes: SynAttributes *
......@@ -1749,7 +1395,7 @@ type SynMemberDefn =
ident: Ident *
typeOpt: SynType option *
propKind: SynMemberKind *
memberFlags:(SynMemberKind -> SynMemberFlags) *
memberFlags: (SynMemberKind -> SynMemberFlags) *
xmlDoc: PreXmlDoc *
accessibility: SynAccess option *
equalsRange: range *
......@@ -1760,27 +1406,24 @@ type SynMemberDefn =
member d.Range =
match d with
| SynMemberDefn.Member (range=m)
| SynMemberDefn.Interface (range=m)
| SynMemberDefn.Open (range=m)
| SynMemberDefn.LetBindings (range=m)
| SynMemberDefn.ImplicitCtor (range=m)
| SynMemberDefn.ImplicitInherit (range=m)
| SynMemberDefn.AbstractSlot (range=m)
| SynMemberDefn.Inherit (range=m)
| SynMemberDefn.ValField (range=m)
| SynMemberDefn.AutoProperty (range=m)
| SynMemberDefn.NestedType (range=m) -> m
| SynMemberDefn.Member (range = m)
| SynMemberDefn.Interface (range = m)
| SynMemberDefn.Open (range = m)
| SynMemberDefn.LetBindings (range = m)
| SynMemberDefn.ImplicitCtor (range = m)
| SynMemberDefn.ImplicitInherit (range = m)
| SynMemberDefn.AbstractSlot (range = m)
| SynMemberDefn.Inherit (range = m)
| SynMemberDefn.ValField (range = m)
| SynMemberDefn.AutoProperty (range = m)
| SynMemberDefn.NestedType (range = m) -> m
type SynMemberDefns = SynMemberDefn list
[<NoEquality; NoComparison;RequireQualifiedAccess>]
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynModuleDecl =
| ModuleAbbrev of
ident: Ident *
longId: LongIdent *
range: range
| ModuleAbbrev of ident: Ident * longId: LongIdent * range: range
| NestedModule of
moduleInfo: SynComponentInfo *
......@@ -1790,53 +1433,37 @@ type SynModuleDecl =
range: range *
trivia: SynModuleDeclNestedModuleTrivia
| Let of
isRecursive: bool *
bindings: SynBinding list *
range: range
| Let of isRecursive: bool * bindings: SynBinding list * range: range
| Expr of
expr: SynExpr *
range: range
| Expr of expr: SynExpr * range: range
| Types of
typeDefns: SynTypeDefn list *
range: range
| Types of typeDefns: SynTypeDefn list * range: range
| Exception of
exnDefn: SynExceptionDefn *
range: range
| Exception of exnDefn: SynExceptionDefn * range: range
| Open of
target: SynOpenDeclTarget *
range: range
| Open of target: SynOpenDeclTarget * range: range
| Attributes of
attributes: SynAttributes *
range: range
| Attributes of attributes: SynAttributes * range: range
| HashDirective of
hashDirective: ParsedHashDirective *
range: range
| HashDirective of hashDirective: ParsedHashDirective * range: range
| NamespaceFragment of
fragment: SynModuleOrNamespace
| NamespaceFragment of fragment: SynModuleOrNamespace
member d.Range =
match d with
| SynModuleDecl.ModuleAbbrev (range=m)
| SynModuleDecl.NestedModule (range=m)
| SynModuleDecl.Let (range=m)
| SynModuleDecl.Expr (range=m)
| SynModuleDecl.Types (range=m)
| SynModuleDecl.Exception (range=m)
| SynModuleDecl.Open (range=m)
| SynModuleDecl.HashDirective (range=m)
| SynModuleDecl.NamespaceFragment (SynModuleOrNamespace (range=m))
| SynModuleDecl.Attributes (range=m) -> m
| SynModuleDecl.ModuleAbbrev (range = m)
| SynModuleDecl.NestedModule (range = m)
| SynModuleDecl.Let (range = m)
| SynModuleDecl.Expr (range = m)
| SynModuleDecl.Types (range = m)
| SynModuleDecl.Exception (range = m)
| SynModuleDecl.Open (range = m)
| SynModuleDecl.HashDirective (range = m)
| SynModuleDecl.NamespaceFragment (SynModuleOrNamespace (range = m))
| SynModuleDecl.Attributes (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynOpenDeclTarget =
type SynOpenDeclTarget =
| ModuleOrNamespace of longId: LongIdent * range: range
......@@ -1844,24 +1471,17 @@ type SynOpenDeclTarget =
member this.Range =
match this with
| ModuleOrNamespace (range=m) -> m
| Type (range=m) -> m
| ModuleOrNamespace (range = m) -> m
| Type (range = m) -> m
[<NoEquality; NoComparison>]
type SynExceptionSig =
| SynExceptionSig of
exnRepr: SynExceptionDefnRepr *
withKeyword: range option *
members: SynMemberSig list *
range: range
| SynExceptionSig of exnRepr: SynExceptionDefnRepr * withKeyword: range option * members: SynMemberSig list * range: range
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynModuleSigDecl =
| ModuleAbbrev of
ident: Ident *
longId: LongIdent *
range: range
| ModuleAbbrev of ident: Ident * longId: LongIdent * range: range
| NestedModule of
moduleInfo: SynComponentInfo *
......@@ -1870,38 +1490,28 @@ type SynModuleSigDecl =
range: range *
trivia: SynModuleSigDeclNestedModuleTrivia
| Val of
valSig: SynValSig * range: range
| Val of valSig: SynValSig * range: range
| Types of
types: SynTypeDefnSig list *
range: range
| Types of types: SynTypeDefnSig list * range: range
| Exception of
exnSig: SynExceptionSig *
range: range
| Exception of exnSig: SynExceptionSig * range: range
| Open of
target: SynOpenDeclTarget *
range: range
| Open of target: SynOpenDeclTarget * range: range
| HashDirective of
hashDirective: ParsedHashDirective *
range: range
| HashDirective of hashDirective: ParsedHashDirective * range: range
| NamespaceFragment of
SynModuleOrNamespaceSig
| NamespaceFragment of SynModuleOrNamespaceSig
member d.Range =
match d with
| SynModuleSigDecl.ModuleAbbrev (range=m)
| SynModuleSigDecl.NestedModule (range=m)
| SynModuleSigDecl.Val (range=m)
| SynModuleSigDecl.Types (range=m)
| SynModuleSigDecl.Exception (range=m)
| SynModuleSigDecl.Open (range=m)
| SynModuleSigDecl.NamespaceFragment (SynModuleOrNamespaceSig.SynModuleOrNamespaceSig(range=m))
| SynModuleSigDecl.HashDirective (range=m) -> m
| SynModuleSigDecl.ModuleAbbrev (range = m)
| SynModuleSigDecl.NestedModule (range = m)
| SynModuleSigDecl.Val (range = m)
| SynModuleSigDecl.Types (range = m)
| SynModuleSigDecl.Exception (range = m)
| SynModuleSigDecl.Open (range = m)
| SynModuleSigDecl.NamespaceFragment (SynModuleOrNamespaceSig.SynModuleOrNamespaceSig (range = m))
| SynModuleSigDecl.HashDirective (range = m) -> m
[<Struct; RequireQualifiedAccess>]
type SynModuleOrNamespaceKind =
......@@ -1915,7 +1525,8 @@ type SynModuleOrNamespaceKind =
member x.IsModule =
match x with
| NamedModule | AnonModule -> true
| NamedModule
| AnonModule -> true
| _ -> false
[<NoEquality; NoComparison>]
......@@ -1933,7 +1544,7 @@ type SynModuleOrNamespace =
member this.Range =
match this with
| SynModuleOrNamespace (range=m) -> m
| SynModuleOrNamespace (range = m) -> m
[<NoEquality; NoComparison>]
type SynModuleOrNamespaceSig =
......@@ -1950,34 +1561,27 @@ type SynModuleOrNamespaceSig =
member this.Range =
match this with
| SynModuleOrNamespaceSig (range=m) -> m
| SynModuleOrNamespaceSig (range = m) -> m
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type ParsedHashDirectiveArgument =
| String of value: string * stringKind: SynStringKind * range: range
| SourceIdentifier of constant: string * value: string * range: range
| 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
member this.Range =
match this with
| ParsedHashDirectiveArgument.String (range = m)
| ParsedHashDirectiveArgument.SourceIdentifier (range = m) -> m
[<NoEquality; NoComparison>]
type ParsedHashDirective =
| ParsedHashDirective of
ident: string *
args: ParsedHashDirectiveArgument list *
range: range
type ParsedHashDirective = ParsedHashDirective of ident: string * args: ParsedHashDirectiveArgument list * range: range
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type ParsedImplFileFragment =
| AnonModule of
decls: SynModuleDecl list *
range: range
| AnonModule of decls: SynModuleDecl list * range: range
| NamedModule of
namedModule: SynModuleOrNamespace
| NamedModule of namedModule: SynModuleOrNamespace
| NamespaceFragment of
longId: LongIdent *
......@@ -1992,12 +1596,9 @@ type ParsedImplFileFragment =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type ParsedSigFileFragment =
| AnonModule of
decls: SynModuleSigDecl list *
range: range
| AnonModule of decls: SynModuleSigDecl list * range: range
| NamedModule of
namedModule: SynModuleOrNamespaceSig
| NamedModule of namedModule: SynModuleOrNamespaceSig
| NamespaceFragment of
longId: LongIdent *
......@@ -2011,29 +1612,18 @@ type ParsedSigFileFragment =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type ParsedScriptInteraction =
| Definitions of
defns: SynModuleDecl list *
range: range
| Definitions of defns: SynModuleDecl list * range: range
| HashDirective of
hashDirective: ParsedHashDirective *
range: range
| HashDirective of hashDirective: ParsedHashDirective * range: range
[<NoEquality; NoComparison>]
type ParsedImplFile =
| ParsedImplFile of
hashDirectives: ParsedHashDirective list *
fragments: ParsedImplFileFragment list
type ParsedImplFile = ParsedImplFile of hashDirectives: ParsedHashDirective list * fragments: ParsedImplFileFragment list
[<NoEquality; NoComparison>]
type ParsedSigFile =
| ParsedSigFile of
hashDirectives: ParsedHashDirective list *
fragments: ParsedSigFileFragment list
type ParsedSigFile = ParsedSigFile of hashDirectives: ParsedHashDirective list * fragments: ParsedSigFileFragment list
[<RequireQualifiedAccess>]
type ScopedPragma =
| WarningOff of range: range * warningNumber: int
type ScopedPragma = WarningOff of range: range * warningNumber: int
[<NoEquality; NoComparison>]
type QualifiedNameOfFile =
......@@ -2075,12 +1665,12 @@ type ParsedInput =
member inp.FileName =
match inp with
| ParsedInput.ImplFile (ParsedImplFileInput (fileName=fileName))
| ParsedInput.SigFile (ParsedSigFileInput (fileName=fileName)) -> fileName
| ParsedInput.ImplFile (ParsedImplFileInput (fileName = fileName))
| ParsedInput.SigFile (ParsedSigFileInput (fileName = fileName)) -> fileName
member inp.Range =
match inp with
| ParsedInput.ImplFile (ParsedImplFileInput (modules=SynModuleOrNamespace(range=m) :: _))
| ParsedInput.SigFile (ParsedSigFileInput (modules=SynModuleOrNamespaceSig(range=m) :: _)) -> m
| ParsedInput.ImplFile (ParsedImplFileInput (fileName=fileName))
| ParsedInput.SigFile (ParsedSigFileInput (fileName=fileName)) -> rangeN fileName 0
| ParsedInput.ImplFile (ParsedImplFileInput(modules = SynModuleOrNamespace (range = m) :: _))
| ParsedInput.SigFile (ParsedSigFileInput(modules = SynModuleOrNamespaceSig (range = m) :: _)) -> m
| ParsedInput.ImplFile (ParsedImplFileInput (fileName = fileName))
| ParsedInput.SigFile (ParsedSigFileInput (fileName = fileName)) -> rangeN fileName 0
......@@ -16,7 +16,10 @@ type SynArgNameGenerator() =
let mutable count = 0
let generatedArgNamePrefix = "_arg"
member _.New() : string = count <- count + 1; generatedArgNamePrefix + string count
member _.New() : string =
count <- count + 1
generatedArgNamePrefix + string count
member _.Reset() = count <- 0
let ident (s, r) = Ident(s, r)
......@@ -34,76 +37,84 @@ let textOfLid lid = textOfPath (pathOfLid lid)
let rangeOfLid (lid: Ident list) =
match lid with
| [] -> failwith "rangeOfLid"
| [id] -> id.idRange
| [ id ] -> id.idRange
| h :: t -> unionRanges h.idRange (List.last t).idRange
let mkSynId m s = Ident(s, m)
let pathToSynLid m p = List.map (mkSynId m) p
let mkSynIdGet m n = SynExpr.Ident (mkSynId m n)
let mkSynIdGet m n = SynExpr.Ident(mkSynId m n)
let mkSynLidGet m path n =
let lid = pathToSynLid m path @ [mkSynId m n]
let lid = pathToSynLid m path @ [ mkSynId m n ]
let dots = List.replicate (lid.Length - 1) m
let trivia: IdentTrivia option list = List.replicate lid.Length None
SynExpr.LongIdent (false, SynLongIdent(lid, dots, trivia), None, m)
SynExpr.LongIdent(false, SynLongIdent(lid, dots, trivia), None, m)
let mkSynIdGetWithAlt m id altInfo =
match altInfo with
| None -> SynExpr.Ident id
| _ -> SynExpr.LongIdent (false, SynLongIdent([id], [], [None]), altInfo, m)
| _ -> SynExpr.LongIdent(false, SynLongIdent([ id ], [], [ None ]), altInfo, m)
let mkSynSimplePatVar isOpt id = SynSimplePat.Id (id, None, false, false, isOpt, id.idRange)
let mkSynSimplePatVar isOpt id =
SynSimplePat.Id(id, None, false, false, isOpt, id.idRange)
let mkSynCompGenSimplePatVar id = SynSimplePat.Id (id, None, true, false, false, id.idRange)
let mkSynCompGenSimplePatVar id =
SynSimplePat.Id(id, None, true, false, false, id.idRange)
let (|SynSingleIdent|_|) x =
match x with
| SynLongIdent ([ id ], _, _) -> Some id
| _ -> None
/// Match a long identifier, including the case for single identifiers which gets a more optimized node in the syntax tree.
let (|LongOrSingleIdent|_|) inp =
match inp with
| SynExpr.LongIdent (isOpt, lidwd, altId, _m) -> Some (isOpt, lidwd, altId, lidwd.RangeWithoutAnyExtraDot)
| SynExpr.Ident id -> Some (false, SynLongIdent([id], [], [None]), None, id.idRange)
| SynExpr.LongIdent (isOpt, lidwd, altId, _m) -> Some(isOpt, lidwd, altId, lidwd.RangeWithoutAnyExtraDot)
| SynExpr.Ident id -> Some(false, SynLongIdent([ id ], [], [ None ]), None, id.idRange)
| _ -> None
let (|SingleIdent|_|) inp =
match inp with
| SynExpr.LongIdent (false, SynLongIdent([id], _, _), None, _) -> Some id
| SynExpr.LongIdent (false, SynSingleIdent (id), None, _) -> Some id
| SynExpr.Ident id -> Some id
| _ -> None
let (|SynBinOp|_|) input =
match input with
| SynExpr.App (ExprAtomicFlag.NonAtomic, false, SynExpr.App (ExprAtomicFlag.NonAtomic, true, SynExpr.LongIdent (longDotId = SynLongIdent(id = [synId])), x1, _m1), x2, _m2) ->
Some (synId, x1, x2)
| SynExpr.App (ExprAtomicFlag.NonAtomic,
false,
SynExpr.App (ExprAtomicFlag.NonAtomic, true, SynExpr.LongIdent(longDotId = SynLongIdent(id = [ synId ])), x1, _m1),
x2,
_m2) -> Some(synId, x1, x2)
| _ -> None
let (|SynPipeRight|_|) input =
match input with
| SynBinOp (synId, x1, x2) when synId.idText = "op_PipeRight" -> Some (x1, x2)
| SynBinOp (synId, x1, x2) when synId.idText = "op_PipeRight" -> Some(x1, x2)
| _ -> None
let (|SynPipeRight2|_|) input =
match input with
| SynBinOp (synId, SynExpr.Paren(SynExpr.Tuple(false, [x1a; x1b], _, _), _, _, _), x2)
when synId.idText = "op_PipeRight2" ->
Some (x1a, x1b, x2)
| SynBinOp (synId, SynExpr.Paren (SynExpr.Tuple (false, [ x1a; x1b ], _, _), _, _, _), x2) when synId.idText = "op_PipeRight2" ->
Some(x1a, x1b, x2)
| _ -> None
let (|SynPipeRight3|_|) input =
match input with
| SynBinOp (synId, SynExpr.Paren(SynExpr.Tuple(false, [x1a; x1b; x1c], _, _), _, _, _), x2)
when synId.idText = "op_PipeRight3" ->
Some (x1a, x1b, x1c, x2)
| SynBinOp (synId, SynExpr.Paren (SynExpr.Tuple (false, [ x1a; x1b; x1c ], _, _), _, _, _), x2) when synId.idText = "op_PipeRight3" ->
Some(x1a, x1b, x1c, x2)
| _ -> None
let (|SynAndAlso|_|) input =
match input with
| SynBinOp (synId, x1, x2) when synId.idText = "op_BooleanAnd" -> Some (x1, x2)
| SynBinOp (synId, x1, x2) when synId.idText = "op_BooleanAnd" -> Some(x1, x2)
| _ -> None
let (|SynOrElse|_|) input =
match input with
| SynBinOp (synId, x1, x2) when synId.idText = "op_BooleanOr" -> Some (x1, x2)
| SynBinOp (synId, x1, x2) when synId.idText = "op_BooleanOr" -> Some(x1, x2)
| _ -> None
/// This affects placement of debug points
......@@ -147,37 +158,44 @@ let rec IsControlFlowExpression e =
// However these do not have side-effect and do not get a debug point recognised by ValidateBreakpointLocation.
let IsDebugPointBinding synPat synExpr =
not (IsControlFlowExpression synExpr) &&
// Don't yield the binding sequence point if there are any arguments, i.e. we're defining a function or a method
let isFunction =
match synPat with
| SynPat.LongIdent (argPats=SynArgPats.Pats args; typarDecls=typarDecls) when not args.IsEmpty || typarDecls.IsSome -> true
| _ -> false
not isFunction
not (IsControlFlowExpression synExpr)
&& let isFunction =
match synPat with
| SynPat.LongIdent (argPats = SynArgPats.Pats args; typarDecls = typarDecls) when not args.IsEmpty || typarDecls.IsSome -> true
| _ -> false in
not isFunction
let inline unionRangeWithXmlDoc (xmlDoc: PreXmlDoc) range =
if xmlDoc.IsEmpty then range else unionRanges xmlDoc.Range range
if xmlDoc.IsEmpty then
range
else
unionRanges xmlDoc.Range range
let mkSynAnonField (ty: SynType, xmlDoc) = SynField([], false, None, ty, false, xmlDoc, None, unionRangeWithXmlDoc xmlDoc ty.Range)
let mkSynAnonField (ty: SynType, xmlDoc) =
SynField([], false, None, ty, false, xmlDoc, None, unionRangeWithXmlDoc xmlDoc ty.Range)
let mkSynNamedField (ident, ty: SynType, xmlDoc, m) = SynField([], false, Some ident, ty, false, xmlDoc, None, m)
let mkSynNamedField (ident, ty: SynType, xmlDoc, m) =
SynField([], false, Some ident, ty, false, xmlDoc, None, m)
let mkSynPatVar vis (id: Ident) = SynPat.Named (SynIdent(id, None), false, vis, id.idRange)
let mkSynPatVar vis (id: Ident) =
SynPat.Named(SynIdent(id, None), false, vis, id.idRange)
let mkSynThisPatVar (id: Ident) = SynPat.Named (SynIdent(id, None), true, None, id.idRange)
let mkSynThisPatVar (id: Ident) =
SynPat.Named(SynIdent(id, None), true, None, id.idRange)
let mkSynPatMaybeVar lidwd vis m = SynPat.LongIdent (lidwd, None, None, None, SynArgPats.Pats [], vis, m)
let mkSynPatMaybeVar lidwd vis m =
SynPat.LongIdent(lidwd, None, None, None, SynArgPats.Pats [], vis, m)
/// Extract the argument for patterns corresponding to the declaration of 'new ... = ...'
let (|SynPatForConstructorDecl|_|) x =
match x with
| SynPat.LongIdent (longDotId=SynLongIdent([_], _, _); argPats=SynArgPats.Pats [arg]) -> Some arg
| SynPat.LongIdent (longDotId = SynSingleIdent _; argPats = SynArgPats.Pats [ arg ]) -> Some arg
| _ -> None
/// Recognize the '()' in 'new()'
let (|SynPatForNullaryArgs|_|) x =
match x with
| SynPat.Paren(SynPat.Const(SynConst.Unit, _), _) -> Some()
| SynPat.Paren (SynPat.Const (SynConst.Unit, _), _) -> Some()
| _ -> None
let (|SynExprErrorSkip|) (p: SynExpr) =
......@@ -187,35 +205,29 @@ let (|SynExprErrorSkip|) (p: SynExpr) =
let (|SynExprParen|_|) (e: SynExpr) =
match e with
| SynExpr.Paren (SynExprErrorSkip e, a, b, c) -> Some (e, a, b, c)
| SynExpr.Paren (SynExprErrorSkip e, a, b, c) -> Some(e, a, b, c)
| _ -> None
let (|SynPatErrorSkip|) (p: SynPat) =
match p with
| SynPat.FromParseError(p, _) -> p
| SynPat.FromParseError (p, _) -> p
| _ -> p
/// Push non-simple parts of a patten match over onto the r.h.s. of a lambda.
/// Return a simple pattern and a function to build a match on the r.h.s. if the pattern is complex
let rec SimplePatOfPat (synArgNameGenerator: SynArgNameGenerator) p =
match p with
| SynPat.Typed(p', ty, m) ->
| SynPat.Typed (p', ty, m) ->
let p2, laterF = SimplePatOfPat synArgNameGenerator p'
SynSimplePat.Typed(p2, ty, m),
laterF
SynSimplePat.Typed(p2, ty, m), laterF
| SynPat.Attrib(p', attribs, m) ->
| SynPat.Attrib (p', attribs, m) ->
let p2, laterF = SimplePatOfPat synArgNameGenerator p'
SynSimplePat.Attrib(p2, attribs, m),
laterF
SynSimplePat.Attrib(p2, attribs, m), laterF
| SynPat.Named (SynIdent(v,_), thisV, _, m) ->
SynSimplePat.Id (v, None, false, thisV, false, m),
None
| SynPat.Named (SynIdent (v, _), thisV, _, m) -> SynSimplePat.Id(v, None, false, thisV, false, m), None
| SynPat.OptionalVal (v, m) ->
SynSimplePat.Id (v, None, false, false, true, m),
None
| SynPat.OptionalVal (v, m) -> SynSimplePat.Id(v, None, false, false, true, m), None
| SynPat.Paren (p, _) -> SimplePatOfPat synArgNameGenerator p
......@@ -223,18 +235,21 @@ let rec SimplePatOfPat (synArgNameGenerator: SynArgNameGenerator) p =
| _ ->
let m = p.Range
let isCompGen, altNameRefCell, id, item =
match p with
| SynPat.LongIdent(longDotId=SynLongIdent([id], _, _); typarDecls=None; argPats=SynArgPats.Pats []; accessibility=None) ->
| SynPat.LongIdent (longDotId = SynSingleIdent (id); typarDecls = None; argPats = SynArgPats.Pats []; accessibility = None) ->
// The pattern is 'V' or some other capitalized identifier.
// It may be a real variable, in which case we want to maintain its name.
// But it may also be a nullary union case or some other identifier.
// In this case, we want to use an alternate compiler generated name for the hidden variable.
let altNameRefCell = Some (ref (SynSimplePatAlternativeIdInfo.Undecided (mkSynId m (synArgNameGenerator.New()))))
let altNameRefCell =
Some(ref (SynSimplePatAlternativeIdInfo.Undecided(mkSynId m (synArgNameGenerator.New()))))
let item = mkSynIdGetWithAlt m id altNameRefCell
false, altNameRefCell, id, item
| SynPat.Named(SynIdent(ident,_), _, _, _)
| SynPat.As(_, SynPat.Named(SynIdent(ident,_), _, _, _), _) ->
| SynPat.Named (SynIdent (ident, _), _, _, _)
| SynPat.As (_, SynPat.Named (SynIdent (ident, _), _, _, _), _) ->
// named pats should be referred to as their name in docs, tooltips, etc.
let item = mkSynIdGet m ident.idText
false, None, ident, item
......@@ -243,58 +258,67 @@ let rec SimplePatOfPat (synArgNameGenerator: SynArgNameGenerator) p =
let id = mkSynId m nm
let item = mkSynIdGet m nm
true, None, id, item
let fn =
match p with
| SynPat.Wild _ -> None
| _ ->
Some (fun e ->
let clause = SynMatchClause(p, None, e, m, DebugPointAtTarget.No, SynMatchClauseTrivia.Zero)
Some(fun e ->
let clause =
SynMatchClause(p, None, e, m, DebugPointAtTarget.No, SynMatchClauseTrivia.Zero)
let artificialMatchRange = (unionRanges m e.Range).MakeSynthetic()
SynExpr.Match (DebugPointAtBinding.NoneAtInvisible, item, [clause], artificialMatchRange, { MatchKeyword = artificialMatchRange
WithKeyword = artificialMatchRange }))
SynSimplePat.Id (id, altNameRefCell, isCompGen, false, false, id.idRange), fn
let trivia =
{
MatchKeyword = artificialMatchRange
WithKeyword = artificialMatchRange
}
let appFunOpt funOpt x = match funOpt with None -> x | Some f -> f x
SynExpr.Match(DebugPointAtBinding.NoneAtInvisible, item, [ clause ], artificialMatchRange, trivia))
let composeFunOpt funOpt1 funOpt2 = match funOpt2 with None -> funOpt1 | Some f -> Some (fun x -> appFunOpt funOpt1 (f x))
SynSimplePat.Id(id, altNameRefCell, isCompGen, false, false, id.idRange), fn
let appFunOpt funOpt x =
match funOpt with
| None -> x
| Some f -> f x
let composeFunOpt funOpt1 funOpt2 =
match funOpt2 with
| None -> funOpt1
| Some f -> Some(fun x -> appFunOpt funOpt1 (f x))
let rec SimplePatsOfPat synArgNameGenerator p =
match p with
| SynPat.FromParseError (p, _) -> SimplePatsOfPat synArgNameGenerator p
| SynPat.Typed(p', ty, m) ->
| SynPat.Typed (p', ty, m) ->
let p2, laterF = SimplePatsOfPat synArgNameGenerator p'
SynSimplePats.Typed(p2, ty, m),
laterF
SynSimplePats.Typed(p2, ty, m), laterF
| SynPat.Tuple (false, ps, m)
| SynPat.Paren(SynPat.Tuple (false, ps, _), m) ->
| SynPat.Paren (SynPat.Tuple (false, ps, _), m) ->
let sps = List.map (SimplePatOfPat synArgNameGenerator) ps
let ps2, laterF =
List.foldBack
(fun (p', rhsf) (ps', rhsf') ->
p':: ps',
(composeFunOpt rhsf rhsf'))
(List.map (SimplePatOfPat synArgNameGenerator) ps)
([], None)
SynSimplePats.SimplePats (ps2, m),
laterF
List.foldBack (fun (p', rhsf) (ps', rhsf') -> p' :: ps', (composeFunOpt rhsf rhsf')) sps ([], None)
SynSimplePats.SimplePats(ps2, m), laterF
| SynPat.Paren(SynPat.Const (SynConst.Unit, m), _)
| SynPat.Paren (SynPat.Const (SynConst.Unit, m), _)
| SynPat.Const (SynConst.Unit, m) ->
SynSimplePats.SimplePats ([], m),
None
| SynPat.Const (SynConst.Unit, m) -> SynSimplePats.SimplePats([], m), None
| _ ->
let m = p.Range
let sp, laterF = SimplePatOfPat synArgNameGenerator p
SynSimplePats.SimplePats ([sp], m), laterF
SynSimplePats.SimplePats([ sp ], m), laterF
let PushPatternToExpr synArgNameGenerator isMember pat (rhs: SynExpr) =
let nowPats, laterF = SimplePatsOfPat synArgNameGenerator pat
nowPats, SynExpr.Lambda (isMember, false, nowPats, appFunOpt laterF rhs, None, rhs.Range, SynExprLambdaTrivia.Zero)
nowPats, SynExpr.Lambda(isMember, false, nowPats, appFunOpt laterF rhs, None, rhs.Range, SynExprLambdaTrivia.Zero)
let private isSimplePattern pat =
let _nowPats, laterF = SimplePatsOfPat (SynArgNameGenerator()) pat
......@@ -311,66 +335,72 @@ let PushCurriedPatternsToExpr synArgNameGenerator wholem isMember pats arrow rhs
// First phase: Fold back, from right to left, pushing patterns into r.h.s. expr
let spatsl, rhs =
(pats, ([], rhs))
||> List.foldBack (fun arg (spatsl, body) ->
let spats, bodyf = SimplePatsOfPat synArgNameGenerator arg
// accumulate the body. This builds "let (UnionCase y) = tmp2 in body"
let body = appFunOpt bodyf body
// accumulate the patterns
let spatsl = spats :: spatsl
(spatsl, body))
||> List.foldBack (fun arg (spatsl, body) ->
let spats, bodyf = SimplePatsOfPat synArgNameGenerator arg
// accumulate the body. This builds "let (UnionCase y) = tmp2 in body"
let body = appFunOpt bodyf body
// accumulate the patterns
let spatsl = spats :: spatsl
(spatsl, body))
// Second phase: build lambdas. Mark subsequent ones with "true" indicating they are part of an iterated sequence of lambdas
let expr =
match spatsl with
| [] -> rhs
| h :: t ->
let expr = List.foldBack (fun spats e -> SynExpr.Lambda (isMember, true, spats, e, None, wholem, { ArrowRange = arrow })) t rhs
let expr = SynExpr.Lambda (isMember, false, h, expr, Some (pats, rhs), wholem, { ArrowRange = arrow })
let expr =
List.foldBack (fun spats e -> SynExpr.Lambda(isMember, true, spats, e, None, wholem, { ArrowRange = arrow })) t rhs
let expr =
SynExpr.Lambda(isMember, false, h, expr, Some(pats, rhs), wholem, { ArrowRange = arrow })
expr
spatsl, expr
let opNameParenGet = CompileOpName parenGet
let opNameParenGet = CompileOpName parenGet
let opNameQMark = CompileOpName qmark
let mkSynOperator (opm:range) (oper:string) =
let mkSynOperator (opm: range) (oper: string) =
let trivia =
if oper.StartsWith("~") && ((opm.EndColumn - opm.StartColumn) = (oper.Length - 1)) then
// PREFIX_OP token where the ~ was actually absent
IdentTrivia.OriginalNotation (string(oper.[1..]))
IdentTrivia.OriginalNotation(string (oper.[1..]))
else
IdentTrivia.OriginalNotation oper
SynExpr.LongIdent(false, SynLongIdent([ident(CompileOpName oper, opm)], [], [Some trivia]), None, opm)
SynExpr.LongIdent(false, SynLongIdent([ ident (CompileOpName oper, opm) ], [], [ Some trivia ]), None, opm)
let mkSynInfix opm (l: SynExpr) oper (r: SynExpr) =
let firstTwoRange = unionRanges l.Range opm
let wholeRange = unionRanges l.Range r.Range
let app1 = SynExpr.App (ExprAtomicFlag.NonAtomic, true, mkSynOperator opm oper, l, firstTwoRange)
SynExpr.App (ExprAtomicFlag.NonAtomic, false, app1, r, wholeRange)
let app1 =
SynExpr.App(ExprAtomicFlag.NonAtomic, true, mkSynOperator opm oper, l, firstTwoRange)
SynExpr.App(ExprAtomicFlag.NonAtomic, false, app1, r, wholeRange)
let mkSynBifix m oper x1 x2 =
let app1 = SynExpr.App (ExprAtomicFlag.NonAtomic, true, mkSynOperator m oper, x1, m)
SynExpr.App (ExprAtomicFlag.NonAtomic, false, app1, x2, m)
let app1 = SynExpr.App(ExprAtomicFlag.NonAtomic, true, mkSynOperator m oper, x1, m)
SynExpr.App(ExprAtomicFlag.NonAtomic, false, app1, x2, m)
let mkSynTrifix m oper x1 x2 x3 =
let app1 = SynExpr.App (ExprAtomicFlag.NonAtomic, true, mkSynOperator m oper, x1, m)
let app2 = SynExpr.App (ExprAtomicFlag.NonAtomic, false, app1, x2, m)
SynExpr.App (ExprAtomicFlag.NonAtomic, false, app2, x3, m)
let mkSynTrifix m oper x1 x2 x3 =
let app1 = SynExpr.App(ExprAtomicFlag.NonAtomic, true, mkSynOperator m oper, x1, m)
let app2 = SynExpr.App(ExprAtomicFlag.NonAtomic, false, app1, x2, m)
SynExpr.App(ExprAtomicFlag.NonAtomic, false, app2, x3, m)
let mkSynPrefixPrim opm m oper x =
SynExpr.App (ExprAtomicFlag.NonAtomic, false, mkSynOperator opm oper, x, m)
SynExpr.App(ExprAtomicFlag.NonAtomic, false, mkSynOperator opm oper, x, m)
let mkSynPrefix opm m oper x =
if oper = "~&" then
SynExpr.AddressOf (true, x, opm, m)
elif oper = "~&&" then
SynExpr.AddressOf (false, x, opm, m)
else
mkSynPrefixPrim opm m oper x
if oper = "~&" then SynExpr.AddressOf(true, x, opm, m)
elif oper = "~&&" then SynExpr.AddressOf(false, x, opm, m)
else mkSynPrefixPrim opm m oper x
let mkSynCaseName m n = [mkSynId m (CompileOpName n)]
let mkSynCaseName m n = [ mkSynId m (CompileOpName n) ]
let mkSynApp1 f x1 m = SynExpr.App (ExprAtomicFlag.NonAtomic, false, f, x1, m)
let mkSynApp1 f x1 m =
SynExpr.App(ExprAtomicFlag.NonAtomic, false, f, x1, m)
let mkSynApp2 f x1 x2 m = mkSynApp1 (mkSynApp1 f x1 m) x2 m
......@@ -378,106 +408,98 @@ let mkSynApp3 f x1 x2 x3 m = mkSynApp1 (mkSynApp2 f x1 x2 m) x3 m
let mkSynApp4 f x1 x2 x3 x4 m = mkSynApp1 (mkSynApp3 f x1 x2 x3 m) x4 m
let mkSynApp5 f x1 x2 x3 x4 x5 m = mkSynApp1 (mkSynApp4 f x1 x2 x3 x4 m) x5 m
let mkSynApp5 f x1 x2 x3 x4 x5 m =
mkSynApp1 (mkSynApp4 f x1 x2 x3 x4 m) x5 m
let mkSynDotParenSet m a b c = mkSynTrifix m parenSet a b c
let mkSynDotParenSet m a b c = mkSynTrifix m parenSet a b c
let mkSynDotBrackGet m mDot a b = SynExpr.DotIndexedGet (a, b, mDot, m)
let mkSynDotBrackGet m mDot a b = SynExpr.DotIndexedGet(a, b, mDot, m)
let mkSynQMarkSet m a b c = mkSynTrifix m qmarkSet a b c
let mkSynDotParenGet lhsm dotm a b =
let mkSynDotParenGet lhsm dotm a b =
match b with
| SynExpr.Tuple (false, [_;_], _, _) ->
errorR(Deprecated(FSComp.SR.astDeprecatedIndexerNotation(), lhsm))
SynExpr.Const (SynConst.Unit, lhsm)
| SynExpr.Tuple (false, [ _; _ ], _, _) ->
errorR (Deprecated(FSComp.SR.astDeprecatedIndexerNotation (), lhsm))
SynExpr.Const(SynConst.Unit, lhsm)
| SynExpr.Tuple (false, [_;_;_], _, _) ->
errorR(Deprecated(FSComp.SR.astDeprecatedIndexerNotation(), lhsm))
SynExpr.Const (SynConst.Unit, lhsm)
| SynExpr.Tuple (false, [ _; _; _ ], _, _) ->
errorR (Deprecated(FSComp.SR.astDeprecatedIndexerNotation (), lhsm))
SynExpr.Const(SynConst.Unit, lhsm)
| _ -> mkSynInfix dotm a parenGet b
let mkSynUnit m = SynExpr.Const (SynConst.Unit, m)
let mkSynUnit m = SynExpr.Const(SynConst.Unit, m)
let mkSynUnitPat m = SynPat.Const(SynConst.Unit, m)
let mkSynDelay m e =
SynExpr.Lambda (false, false, SynSimplePats.SimplePats ([mkSynCompGenSimplePatVar (mkSynId m "unitVar")], m), e, None, m, SynExprLambdaTrivia.Zero)
let svar = mkSynCompGenSimplePatVar (mkSynId m "unitVar")
SynExpr.Lambda(false, false, SynSimplePats.SimplePats([ svar ], m), e, None, m, SynExprLambdaTrivia.Zero)
let mkSynAssign (l: SynExpr) (r: SynExpr) =
let m = unionRanges l.Range r.Range
match l with
//| SynExpr.Paren (l2, m2) -> mkSynAssign m l2 r
| LongOrSingleIdent(false, v, None, _) -> SynExpr.LongIdentSet (v, r, m)
| SynExpr.DotGet (e, _, v, _) -> SynExpr.DotSet (e, v, r, m)
| SynExpr.DotIndexedGet (e1, e2, mDot, mLeft) -> SynExpr.DotIndexedSet (e1, e2, r, mLeft, mDot, m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (x, y, z, _) -> SynExpr.LibraryOnlyUnionCaseFieldSet (x, y, z, r, m)
| SynExpr.App (_, _, SynExpr.App (_, _, SingleIdent nm, a, _), b, _) when nm.idText = opNameQMark ->
mkSynQMarkSet m a b r
| SynExpr.App (_, _, SynExpr.App (_, _, SingleIdent nm, a, _), b, _) when nm.idText = opNameParenGet ->
mkSynDotParenSet m a b r
| SynExpr.App (_, _, SynExpr.LongIdent (false, v, None, _), x, _) -> SynExpr.NamedIndexedPropertySet (v, x, r, m)
| SynExpr.App (_, _, SynExpr.DotGet (e, _, v, _), x, _) -> SynExpr.DotNamedIndexedPropertySet (e, v, x, r, m)
| l -> SynExpr.Set (l, r, m)
let mkSynDot dotm m l (SynIdent(r, rTrivia)) =
| LongOrSingleIdent (false, v, None, _) -> SynExpr.LongIdentSet(v, r, m)
| SynExpr.DotGet (e, _, v, _) -> SynExpr.DotSet(e, v, r, m)
| SynExpr.DotIndexedGet (e1, e2, mDot, mLeft) -> SynExpr.DotIndexedSet(e1, e2, r, mLeft, mDot, m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (x, y, z, _) -> SynExpr.LibraryOnlyUnionCaseFieldSet(x, y, z, r, m)
| SynExpr.App (_, _, SynExpr.App (_, _, SingleIdent nm, a, _), b, _) when nm.idText = opNameQMark -> mkSynQMarkSet m a b r
| SynExpr.App (_, _, SynExpr.App (_, _, SingleIdent nm, a, _), b, _) when nm.idText = opNameParenGet -> mkSynDotParenSet m a b r
| SynExpr.App (_, _, SynExpr.LongIdent (false, v, None, _), x, _) -> SynExpr.NamedIndexedPropertySet(v, x, r, m)
| SynExpr.App (_, _, SynExpr.DotGet (e, _, v, _), x, _) -> SynExpr.DotNamedIndexedPropertySet(e, v, x, r, m)
| l -> SynExpr.Set(l, r, m)
let mkSynDot dotm m l (SynIdent (r, rTrivia)) =
match l with
| SynExpr.LongIdent (isOpt, SynLongIdent(lid, dots, trivia), None, _) ->
| SynExpr.LongIdent (isOpt, SynLongIdent (lid, dots, trivia), None, _) ->
// REVIEW: MEMORY PERFORMANCE: This list operation is memory intensive (we create a lot of these list nodes)
SynExpr.LongIdent (isOpt, SynLongIdent(lid@[r], dots@[dotm], trivia@[rTrivia]), None, m)
| SynExpr.Ident id ->
SynExpr.LongIdent (false, SynLongIdent([id;r], [dotm], [None; rTrivia]), None, m)
| SynExpr.DotGet (e, dm, SynLongIdent(lid, dots, trivia), _) ->
SynExpr.LongIdent(isOpt, SynLongIdent(lid @ [ r ], dots @ [ dotm ], trivia @ [ rTrivia ]), None, m)
| SynExpr.Ident id -> SynExpr.LongIdent(false, SynLongIdent([ id; r ], [ dotm ], [ None; rTrivia ]), None, m)
| SynExpr.DotGet (e, dm, SynLongIdent (lid, dots, trivia), _) ->
// REVIEW: MEMORY PERFORMANCE: This is memory intensive (we create a lot of these list nodes)
SynExpr.DotGet (e, dm, SynLongIdent(lid@[r], dots@[dotm], trivia@[rTrivia]), m)
| expr ->
SynExpr.DotGet (expr, dotm, SynLongIdent([r], [], [rTrivia]), m)
SynExpr.DotGet(e, dm, SynLongIdent(lid @ [ r ], dots @ [ dotm ], trivia @ [ rTrivia ]), m)
| expr -> SynExpr.DotGet(expr, dotm, SynLongIdent([ r ], [], [ rTrivia ]), m)
let mkSynDotMissing dotm m l =
match l with
| SynExpr.LongIdent (isOpt, SynLongIdent(lid, dots, trivia), None, _) ->
// REVIEW: MEMORY PERFORMANCE: This list operation is memory intensive (we create a lot of these list nodes)
SynExpr.LongIdent (isOpt, SynLongIdent(lid, dots@[dotm], trivia), None, m)
| SynExpr.Ident id ->
SynExpr.LongIdent (false, SynLongIdent([id], [dotm], []), None, m)
| SynExpr.DotGet (e, dm, SynLongIdent(lid, dots, trivia), _) ->
SynExpr.DotGet (e, dm, SynLongIdent(lid, dots@[dotm], trivia), m)// REVIEW: MEMORY PERFORMANCE: This is memory intensive (we create a lot of these list nodes)
| expr ->
SynExpr.DiscardAfterMissingQualificationAfterDot (expr, m)
| SynExpr.LongIdent (isOpt, SynLongIdent (lid, dots, trivia), None, _) ->
// REVIEW: MEMORY PERFORMANCE: This list operation is memory intensive (we create a lot of these list nodes)
SynExpr.LongIdent(isOpt, SynLongIdent(lid, dots @ [ dotm ], trivia), None, m)
| SynExpr.Ident id -> SynExpr.LongIdent(false, SynLongIdent([ id ], [ dotm ], []), None, m)
| SynExpr.DotGet (e, dm, SynLongIdent (lid, dots, trivia), _) -> SynExpr.DotGet(e, dm, SynLongIdent(lid, dots @ [ dotm ], trivia), m) // REVIEW: MEMORY PERFORMANCE: This is memory intensive (we create a lot of these list nodes)
| expr -> SynExpr.DiscardAfterMissingQualificationAfterDot(expr, m)
let mkSynFunMatchLambdas synArgNameGenerator isMember wholem ps arrow e =
let _, e = PushCurriedPatternsToExpr synArgNameGenerator wholem isMember ps arrow e
let _, e = PushCurriedPatternsToExpr synArgNameGenerator wholem isMember ps arrow e
e
let arbExpr (debugStr, range: range) = SynExpr.ArbitraryAfterError (debugStr, range.MakeSynthetic())
let arbExpr (debugStr, range: range) =
SynExpr.ArbitraryAfterError(debugStr, range.MakeSynthetic())
let unionRangeWithListBy projectRangeFromThing m listOfThing =
(m, listOfThing) ||> List.fold (fun m thing -> unionRanges m (projectRangeFromThing thing))
let unionRangeWithListBy projectRangeFromThing m listOfThing =
(m, listOfThing)
||> List.fold (fun m thing -> unionRanges m (projectRangeFromThing thing))
let mkAttributeList attrs range : SynAttributeList list =
[{ Attributes = attrs
Range = range }]
[ { Attributes = attrs; Range = range } ]
let ConcatAttributesLists (attrsLists: SynAttributeList list) =
attrsLists
|> List.map (fun x -> x.Attributes)
|> List.concat
attrsLists |> List.map (fun x -> x.Attributes) |> List.concat
let (|Attributes|) synAttributes =
ConcatAttributesLists synAttributes
let (|Attributes|) synAttributes = ConcatAttributesLists synAttributes
let (|TyparDecls|) (typarDecls: SynTyparDecls option) =
typarDecls
|> Option.map (fun x -> x.TyparDecls)
|> Option.defaultValue []
typarDecls |> Option.map (fun x -> x.TyparDecls) |> Option.defaultValue []
let (|TyparsAndConstraints|) (typarDecls: SynTyparDecls option) =
typarDecls
|> Option.map (fun x -> x.TyparDecls, x.Constraints)
|> Option.defaultValue ([], [])
let (|ValTyparDecls|) (SynValTyparDecls(typarDecls, canInfer)) =
let (|ValTyparDecls|) (SynValTyparDecls (typarDecls, canInfer)) =
typarDecls
|> Option.map (fun x -> x.TyparDecls, x.Constraints, canInfer)
|> Option.defaultValue ([], [], canInfer)
......@@ -490,8 +512,7 @@ let rec stripParenTypes synType =
| SynType.Paren (innerType, _) -> stripParenTypes innerType
| _ -> synType
let (|StripParenTypes|) synType =
stripParenTypes synType
let (|StripParenTypes|) synType = stripParenTypes synType
/// Operations related to the syntactic analysis of arguments of value, function and member definitions and signatures.
module SynInfo =
......@@ -500,7 +521,7 @@ module SynInfo =
let unnamedTopArg1 = SynArgInfo([], false, None)
/// The argument information for a curried argument without a name
let unnamedTopArg = [unnamedTopArg1]
let unnamedTopArg = [ unnamedTopArg1 ]
/// The argument information for a '()' argument
let unitArgData = unnamedTopArg
......@@ -512,53 +533,55 @@ module SynInfo =
let selfMetadata = unnamedTopArg
/// Determine if a syntactic information represents a member without arguments (which is implicitly a property getter)
let HasNoArgs (SynValInfo(args, _)) = isNil args
let HasNoArgs (SynValInfo (args, _)) = isNil args
/// Check if one particular argument is an optional argument. Used when adjusting the
/// types of optional arguments for function and member signatures.
let IsOptionalArg (SynArgInfo(_, isOpt, _)) = isOpt
let IsOptionalArg (SynArgInfo (_, isOpt, _)) = isOpt
/// Check if there are any optional arguments in the syntactic argument information. Used when adjusting the
/// types of optional arguments for function and member signatures.
let HasOptionalArgs (SynValInfo(args, _)) = List.exists (List.exists IsOptionalArg) args
let HasOptionalArgs (SynValInfo (args, _)) =
List.exists (List.exists IsOptionalArg) args
/// Add a parameter entry to the syntactic value information to represent the '()' argument to a property getter. This is
/// used for the implicit '()' argument in property getter signature specifications.
let IncorporateEmptyTupledArgForPropertyGetter (SynValInfo(args, retInfo)) = SynValInfo([] :: args, retInfo)
let IncorporateEmptyTupledArgForPropertyGetter (SynValInfo (args, retInfo)) = SynValInfo([] :: args, retInfo)
/// Add a parameter entry to the syntactic value information to represent the 'this' argument. This is
/// used for the implicit 'this' argument in member signature specifications.
let IncorporateSelfArg (SynValInfo(args, retInfo)) = SynValInfo(selfMetadata :: args, retInfo)
let IncorporateSelfArg (SynValInfo (args, retInfo)) =
SynValInfo(selfMetadata :: args, retInfo)
/// Add a parameter entry to the syntactic value information to represent the value argument for a property setter. This is
/// used for the implicit value argument in property setter signature specifications.
let IncorporateSetterArg (SynValInfo(args, retInfo)) =
let args =
match args with
| [] -> [unnamedTopArg]
| [arg] -> [arg@[unnamedTopArg1]]
| _ -> failwith "invalid setter type"
SynValInfo(args, retInfo)
let IncorporateSetterArg (SynValInfo (args, retInfo)) =
let args =
match args with
| [] -> [ unnamedTopArg ]
| [ arg ] -> [ arg @ [ unnamedTopArg1 ] ]
| _ -> failwith "invalid setter type"
SynValInfo(args, retInfo)
/// Get the argument counts for each curried argument group. Used in some adhoc places in tc.fs.
let AritiesOfArgs (SynValInfo(args, _)) = List.map List.length args
let AritiesOfArgs (SynValInfo (args, _)) = List.map List.length args
/// Get the argument attributes from the syntactic information for an argument.
let AttribsOfArgData (SynArgInfo(Attributes attribs, _, _)) = attribs
let AttribsOfArgData (SynArgInfo (Attributes attribs, _, _)) = attribs
/// Infer the syntactic argument info for a single argument from a simple pattern.
let rec InferSynArgInfoFromSimplePat attribs p =
match p with
| SynSimplePat.Id(nm, _, isCompGen, _, isOpt, _) ->
SynArgInfo(attribs, isOpt, (if isCompGen then None else Some nm))
| SynSimplePat.Typed(a, _, _) -> InferSynArgInfoFromSimplePat attribs a
| SynSimplePat.Attrib(a, attribs2, _) -> InferSynArgInfoFromSimplePat (attribs @ attribs2) a
| SynSimplePat.Id (nm, _, isCompGen, _, isOpt, _) -> SynArgInfo(attribs, isOpt, (if isCompGen then None else Some nm))
| SynSimplePat.Typed (a, _, _) -> InferSynArgInfoFromSimplePat attribs a
| SynSimplePat.Attrib (a, attribs2, _) -> InferSynArgInfoFromSimplePat (attribs @ attribs2) a
/// Infer the syntactic argument info for one or more arguments one or more simple patterns.
let rec InferSynArgInfoFromSimplePats x =
match x with
| SynSimplePats.SimplePats(ps, _) -> List.map (InferSynArgInfoFromSimplePat []) ps
| SynSimplePats.Typed(ps, _, _) -> InferSynArgInfoFromSimplePats ps
| SynSimplePats.SimplePats (ps, _) -> List.map (InferSynArgInfoFromSimplePat []) ps
| SynSimplePats.Typed (ps, _, _) -> InferSynArgInfoFromSimplePats ps
/// Infer the syntactic argument info for one or more arguments a pattern.
let InferSynArgInfoFromPat p =
......@@ -569,8 +592,12 @@ module SynInfo =
/// Make sure only a solitary unit argument has unit elimination
let AdjustArgsForUnitElimination infosForArgs =
match infosForArgs with
| [[]] -> infosForArgs
| _ -> infosForArgs |> List.map (function [] -> unitArgData | x -> x)
| [ [] ] -> infosForArgs
| _ ->
infosForArgs
|> List.map (function
| [] -> unitArgData
| x -> x)
/// Transform a property declared using '[static] member P = expr' to a method taking a "unit" argument.
/// This is similar to IncorporateEmptyTupledArgForPropertyGetter, but applies to member definitions
......@@ -584,18 +611,20 @@ module SynInfo =
/// is an immediate 'fun ... -> ...' or 'function ...' expression. This is noted in the F# language specification.
/// This does not apply to member definitions nor to returns with attributes
let InferLambdaArgs (retInfo: SynArgInfo) origRhsExpr =
if retInfo.Attributes.Length > 0 then [] else
let rec loop e =
match e with
| SynExpr.Lambda (fromMethod=false; args=spats; body=rest) ->
InferSynArgInfoFromSimplePats spats :: loop rest
| _ -> []
loop origRhsExpr
if retInfo.Attributes.Length > 0 then
[]
else
let rec loop e =
match e with
| SynExpr.Lambda (fromMethod = false; args = spats; body = rest) -> InferSynArgInfoFromSimplePats spats :: loop rest
| _ -> []
loop origRhsExpr
let InferSynReturnData (retInfo: SynReturnInfo option) =
match retInfo with
| None -> unnamedRetVal
| Some(SynReturnInfo((_, retInfo), _)) -> retInfo
| Some (SynReturnInfo ((_, retInfo), _)) -> retInfo
let private emptySynValInfo = SynValInfo([], unnamedRetVal)
......@@ -608,12 +637,12 @@ module SynInfo =
let infosForExplicitArgs =
match pat with
| Some(SynPat.LongIdent(argPats=SynArgPats.Pats curriedArgs)) -> List.map InferSynArgInfoFromPat curriedArgs
| Some (SynPat.LongIdent(argPats = SynArgPats.Pats curriedArgs)) -> List.map InferSynArgInfoFromPat curriedArgs
| _ -> []
let explicitArgsAreSimple =
match pat with
| Some(SynPat.LongIdent(argPats=SynArgPats.Pats curriedArgs)) -> List.forall isSimplePattern curriedArgs
| Some (SynPat.LongIdent(argPats = SynArgPats.Pats curriedArgs)) -> List.forall isSimplePattern curriedArgs
| _ -> true
let retInfo = InferSynReturnData retInfo
......@@ -621,13 +650,16 @@ module SynInfo =
match memberFlagsOpt with
| None ->
let infosForLambdaArgs = InferLambdaArgs retInfo origRhsExpr
let infosForArgs = infosForExplicitArgs @ (if explicitArgsAreSimple then infosForLambdaArgs else [])
let infosForArgs =
infosForExplicitArgs
@ (if explicitArgsAreSimple then infosForLambdaArgs else [])
let infosForArgs = AdjustArgsForUnitElimination infosForArgs
SynValData(None, SynValInfo(infosForArgs, retInfo), None)
| Some memFlags ->
let infosForObjArgs =
if memFlags.IsInstance then [ selfMetadata ] else []
| Some memFlags ->
let infosForObjArgs = if memFlags.IsInstance then [ selfMetadata ] else []
let infosForArgs = AdjustMemberArgs memFlags.MemberKind infosForExplicitArgs
let infosForArgs = AdjustArgsForUnitElimination infosForArgs
......@@ -636,259 +668,302 @@ module SynInfo =
SynValData(Some memFlags, SynValInfo(argInfos, retInfo), None)
let mkSynBindingRhs staticOptimizations rhsExpr mRhs retInfo =
let rhsExpr = List.foldBack (fun (c, e1) e2 -> SynExpr.LibraryOnlyStaticOptimization (c, e1, e2, mRhs)) staticOptimizations rhsExpr
let rhsExpr =
List.foldBack (fun (c, e1) e2 -> SynExpr.LibraryOnlyStaticOptimization(c, e1, e2, mRhs)) staticOptimizations rhsExpr
let rhsExpr, retTyOpt =
match retInfo with
| Some (SynReturnInfo((ty, SynArgInfo(rAttribs, _, _)), tym)) ->
SynExpr.Typed (rhsExpr, ty, rhsExpr.Range), Some(SynBindingReturnInfo(ty, tym, rAttribs) )
| Some (SynReturnInfo ((ty, SynArgInfo (rAttribs, _, _)), tym)) ->
SynExpr.Typed(rhsExpr, ty, rhsExpr.Range), Some(SynBindingReturnInfo(ty, tym, rAttribs))
| None -> rhsExpr, None
rhsExpr, retTyOpt
let mkSynBinding (xmlDoc: PreXmlDoc, headPat) (vis, isInline, isMutable, mBind, spBind, retInfo, origRhsExpr, mRhs, staticOptimizations, attrs, memberFlagsOpt, trivia) =
let info = SynInfo.InferSynValData (memberFlagsOpt, Some headPat, retInfo, origRhsExpr)
let mkSynBinding
(xmlDoc: PreXmlDoc, headPat)
(vis, isInline, isMutable, mBind, spBind, retInfo, origRhsExpr, mRhs, staticOptimizations, attrs, memberFlagsOpt, trivia)
=
let info =
SynInfo.InferSynValData(memberFlagsOpt, Some headPat, retInfo, origRhsExpr)
let rhsExpr, retTyOpt = mkSynBindingRhs staticOptimizations origRhsExpr mRhs retInfo
let mBind = unionRangeWithXmlDoc xmlDoc mBind
SynBinding (vis, SynBindingKind.Normal, isInline, isMutable, attrs, xmlDoc, info, headPat, retTyOpt, rhsExpr, mBind, spBind, trivia)
SynBinding(vis, SynBindingKind.Normal, isInline, isMutable, attrs, xmlDoc, info, headPat, retTyOpt, rhsExpr, mBind, spBind, trivia)
let NonVirtualMemberFlags trivia k : SynMemberFlags =
{ MemberKind=k
IsInstance=true
IsDispatchSlot=false
IsOverrideOrExplicitImpl=false
IsFinal=false
Trivia=trivia }
{
MemberKind = k
IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
Trivia = trivia
}
let CtorMemberFlags trivia : SynMemberFlags =
{ MemberKind=SynMemberKind.Constructor
IsInstance=false
IsDispatchSlot=false
IsOverrideOrExplicitImpl=false
IsFinal=false
Trivia=trivia }
{
MemberKind = SynMemberKind.Constructor
IsInstance = false
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
Trivia = trivia
}
let ClassCtorMemberFlags trivia : SynMemberFlags =
{ MemberKind=SynMemberKind.ClassConstructor
IsInstance=false
IsDispatchSlot=false
IsOverrideOrExplicitImpl=false
IsFinal=false
Trivia=trivia }
{
MemberKind = SynMemberKind.ClassConstructor
IsInstance = false
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
Trivia = trivia
}
let OverrideMemberFlags trivia k : SynMemberFlags =
{ MemberKind=k
IsInstance=true
IsDispatchSlot=false
IsOverrideOrExplicitImpl=true
IsFinal=false
Trivia=trivia }
{
MemberKind = k
IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = true
IsFinal = false
Trivia = trivia
}
let AbstractMemberFlags trivia k : SynMemberFlags =
{ MemberKind=k
IsInstance=true
IsDispatchSlot=true
IsOverrideOrExplicitImpl=false
IsFinal=false
Trivia=trivia }
{
MemberKind = k
IsInstance = true
IsDispatchSlot = true
IsOverrideOrExplicitImpl = false
IsFinal = false
Trivia = trivia
}
let StaticMemberFlags trivia k : SynMemberFlags =
{ MemberKind=k
IsInstance=false
IsDispatchSlot=false
IsOverrideOrExplicitImpl=false
IsFinal=false
Trivia=trivia }
{
MemberKind = k
IsInstance = false
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
Trivia = trivia
}
let MemberSynMemberFlagsTrivia (mMember: range) : SynMemberFlagsTrivia =
{ MemberRange = Some mMember
OverrideRange = None
AbstractRange = None
StaticRange = None
DefaultRange = None }
{
MemberRange = Some mMember
OverrideRange = None
AbstractRange = None
StaticRange = None
DefaultRange = None
}
let OverrideSynMemberFlagsTrivia (mOverride: range) : SynMemberFlagsTrivia =
{ MemberRange = None
OverrideRange = Some mOverride
AbstractRange = None
StaticRange = None
DefaultRange = None }
{
MemberRange = None
OverrideRange = Some mOverride
AbstractRange = None
StaticRange = None
DefaultRange = None
}
let StaticMemberSynMemberFlagsTrivia (mStatic: range) (mMember: range) : SynMemberFlagsTrivia =
{ MemberRange = Some mMember
OverrideRange = None
AbstractRange = None
StaticRange = Some mStatic
DefaultRange = None }
{
MemberRange = Some mMember
OverrideRange = None
AbstractRange = None
StaticRange = Some mStatic
DefaultRange = None
}
let DefaultSynMemberFlagsTrivia (mDefault: range) : SynMemberFlagsTrivia =
{ MemberRange = None
OverrideRange = None
AbstractRange = None
StaticRange = None
DefaultRange = Some mDefault }
{
MemberRange = None
OverrideRange = None
AbstractRange = None
StaticRange = None
DefaultRange = Some mDefault
}
let AbstractSynMemberFlagsTrivia (mAbstract: range) : SynMemberFlagsTrivia =
{ MemberRange = None
OverrideRange = None
AbstractRange = Some mAbstract
StaticRange = None
DefaultRange = None }
{
MemberRange = None
OverrideRange = None
AbstractRange = Some mAbstract
StaticRange = None
DefaultRange = None
}
let AbstractMemberSynMemberFlagsTrivia (mAbstract: range) (mMember: range) : SynMemberFlagsTrivia =
{ MemberRange = Some mMember
OverrideRange = None
AbstractRange = Some mAbstract
StaticRange = None
DefaultRange = None }
{
MemberRange = Some mMember
OverrideRange = None
AbstractRange = Some mAbstract
StaticRange = None
DefaultRange = None
}
let inferredTyparDecls = SynValTyparDecls(None, true)
let noInferredTypars = SynValTyparDecls(None, false)
let unionBindingAndMembers (bindings: SynBinding list) (members: SynMemberDefn list): SynBinding list =
[ yield! bindings
yield! List.choose (function | SynMemberDefn.Member(b,_) -> Some b | _ -> None) members ]
let unionBindingAndMembers (bindings: SynBinding list) (members: SynMemberDefn list) : SynBinding list =
[
yield! bindings
yield!
List.choose
(function
| SynMemberDefn.Member (b, _) -> Some b
| _ -> None)
members
]
let rec synExprContainsError inpExpr =
let rec walkBind (SynBinding(expr=synExpr)) = walkExpr synExpr
let rec walkBind (SynBinding (expr = synExpr)) = walkExpr synExpr
and walkExprs es = es |> List.exists walkExpr
and walkBinds es = es |> List.exists walkBind
and walkMatchClauses cl =
cl |> List.exists (fun (SynMatchClause(whenExpr=whenExpr; resultExpr=e)) -> walkExprOpt whenExpr || walkExpr e)
cl
|> List.exists (fun (SynMatchClause (whenExpr = whenExpr; resultExpr = e)) -> walkExprOpt whenExpr || walkExpr e)
and walkExprOpt eOpt = eOpt |> Option.exists walkExpr
and walkExpr e =
match e with
| SynExpr.FromParseError _
| SynExpr.DiscardAfterMissingQualificationAfterDot _
| SynExpr.ArbitraryAfterError _ -> true
| SynExpr.LongIdent _
| SynExpr.Quote _
| SynExpr.LibraryOnlyILAssembly _
| SynExpr.LibraryOnlyStaticOptimization _
| SynExpr.Null _
| SynExpr.Ident _
| SynExpr.ImplicitZero _
| SynExpr.Const _
| SynExpr.Dynamic _ -> false
| SynExpr.TypeTest (e, _, _)
| SynExpr.Upcast (e, _, _)
| SynExpr.AddressOf (_, e, _, _)
| SynExpr.ComputationExpr (_, e, _)
| SynExpr.ArrayOrListComputed (_, e, _)
| SynExpr.Typed (e, _, _)
| SynExpr.FromParseError (e, _)
| SynExpr.Do (e, _)
| SynExpr.Assert (e, _)
| SynExpr.DotGet (e, _, _, _)
| SynExpr.LongIdentSet (_, e, _)
| SynExpr.New (_, _, e, _)
| SynExpr.TypeApp (e, _, _, _, _, _, _)
| SynExpr.LibraryOnlyUnionCaseFieldGet (e, _, _, _)
| SynExpr.Downcast (e, _, _)
| SynExpr.InferredUpcast (e, _)
| SynExpr.InferredDowncast (e, _)
| SynExpr.Lazy (e, _)
| SynExpr.TraitCall (_, _, e, _)
| SynExpr.YieldOrReturn (_, e, _)
| SynExpr.YieldOrReturnFrom (_, e, _)
| SynExpr.DoBang (e, _)
| SynExpr.Fixed (e, _)
| SynExpr.DebugPoint (_, _, e)
| SynExpr.Paren (e, _, _, _) ->
walkExpr e
| SynExpr.NamedIndexedPropertySet (_, e1, e2, _)
| SynExpr.DotSet (e1, _, e2, _)
| SynExpr.Set (e1, e2, _)
| SynExpr.LibraryOnlyUnionCaseFieldSet (e1, _, _, e2, _)
| SynExpr.JoinIn (e1, _, e2, _)
| SynExpr.App (_, _, e1, e2, _) ->
walkExpr e1 || walkExpr e2
| SynExpr.ArrayOrList (_, es, _)
| SynExpr.Tuple (_, es, _, _) ->
walkExprs es
| SynExpr.AnonRecd (_, origExpr, flds, _) ->
(match origExpr with Some (e, _) -> walkExpr e | None -> false) ||
walkExprs (List.map (fun (_, _, e) -> e) flds)
| SynExpr.Record (_, origExpr, fs, _) ->
(match origExpr with Some (e, _) -> walkExpr e | None -> false) ||
let flds = fs |> List.choose (fun (SynExprRecordField(expr=v)) -> v)
walkExprs flds
| SynExpr.ObjExpr (bindings=bs; members=ms; extraImpls=is) ->
let bs = unionBindingAndMembers bs ms
walkBinds bs || walkBinds [ for SynInterfaceImpl(bindings=bs) in is do yield! bs ]
| SynExpr.ForEach (_, _, _, _, _, e1, e2, _)
| SynExpr.While (_, e1, e2, _) ->
walkExpr e1 || walkExpr e2
| SynExpr.For (identBody=e1; toBody=e2; doBody=e3) ->
walkExpr e1 || walkExpr e2 || walkExpr e3
| SynExpr.MatchLambda (_, _, cl, _, _) ->
walkMatchClauses cl
| SynExpr.Lambda (body = e) ->
walkExpr e
| SynExpr.Match (expr=e; clauses=cl) ->
walkExpr e || walkMatchClauses cl
| SynExpr.LetOrUse (bindings=bs; body=e) ->
walkBinds bs || walkExpr e
| SynExpr.TryWith (tryExpr=e; withCases=cl) ->
walkExpr e || walkMatchClauses cl
| SynExpr.TryFinally (tryExpr=e1; finallyExpr=e2) ->
walkExpr e1 || walkExpr e2
| SynExpr.Sequential (_, _, e1, e2, _) ->
walkExpr e1 || walkExpr e2
| SynExpr.SequentialOrImplicitYield (_, e1, e2, _, _) ->
walkExpr e1 || walkExpr e2
| SynExpr.IfThenElse (ifExpr=e1; thenExpr=e2; elseExpr=e3opt) ->
walkExpr e1 || walkExpr e2 || walkExprOpt e3opt
| SynExpr.IndexRange (expr1, _, expr2, _, _, _) ->
(match expr1 with Some e -> walkExpr e | None -> false) ||
(match expr2 with Some e -> walkExpr e | None -> false)
| SynExpr.IndexFromEnd (e, _) ->
walkExpr e
| SynExpr.DotIndexedGet (e1, indexArgs, _, _) ->
walkExpr e1 || walkExpr indexArgs
| SynExpr.DotIndexedSet (e1, indexArgs, e2, _, _, _) ->
walkExpr e1 || walkExpr indexArgs || walkExpr e2
| SynExpr.DotNamedIndexedPropertySet (e1, _, e2, e3, _) ->
walkExpr e1 || walkExpr e2 || walkExpr e3
| SynExpr.MatchBang (expr=e; clauses=cl) ->
walkExpr e || walkMatchClauses cl
| SynExpr.LetOrUseBang (rhs=e1;body=e2;andBangs=es) ->
walkExpr e1 || walkExprs [ for SynExprAndBang(body=e) in es do yield e ] || walkExpr e2
| SynExpr.InterpolatedString (parts, _, _m) ->
walkExprs
(parts |> List.choose (function
| SynInterpolatedStringPart.String _ -> None
| SynInterpolatedStringPart.FillExpr (x, _) -> Some x))
match e with
| SynExpr.FromParseError _
| SynExpr.DiscardAfterMissingQualificationAfterDot _
| SynExpr.ArbitraryAfterError _ -> true
| SynExpr.LongIdent _
| SynExpr.Quote _
| SynExpr.LibraryOnlyILAssembly _
| SynExpr.LibraryOnlyStaticOptimization _
| SynExpr.Null _
| SynExpr.Ident _
| SynExpr.ImplicitZero _
| SynExpr.Const _
| SynExpr.Dynamic _ -> false
| SynExpr.TypeTest (e, _, _)
| SynExpr.Upcast (e, _, _)
| SynExpr.AddressOf (_, e, _, _)
| SynExpr.ComputationExpr (_, e, _)
| SynExpr.ArrayOrListComputed (_, e, _)
| SynExpr.Typed (e, _, _)
| SynExpr.FromParseError (e, _)
| SynExpr.Do (e, _)
| SynExpr.Assert (e, _)
| SynExpr.DotGet (e, _, _, _)
| SynExpr.LongIdentSet (_, e, _)
| SynExpr.New (_, _, e, _)
| SynExpr.TypeApp (e, _, _, _, _, _, _)
| SynExpr.LibraryOnlyUnionCaseFieldGet (e, _, _, _)
| SynExpr.Downcast (e, _, _)
| SynExpr.InferredUpcast (e, _)
| SynExpr.InferredDowncast (e, _)
| SynExpr.Lazy (e, _)
| SynExpr.TraitCall (_, _, e, _)
| SynExpr.YieldOrReturn (_, e, _)
| SynExpr.YieldOrReturnFrom (_, e, _)
| SynExpr.DoBang (e, _)
| SynExpr.Fixed (e, _)
| SynExpr.DebugPoint (_, _, e)
| SynExpr.Paren (e, _, _, _) -> walkExpr e
| SynExpr.NamedIndexedPropertySet (_, e1, e2, _)
| SynExpr.DotSet (e1, _, e2, _)
| SynExpr.Set (e1, e2, _)
| SynExpr.LibraryOnlyUnionCaseFieldSet (e1, _, _, e2, _)
| SynExpr.JoinIn (e1, _, e2, _)
| SynExpr.App (_, _, e1, e2, _) -> walkExpr e1 || walkExpr e2
| SynExpr.ArrayOrList (_, es, _)
| SynExpr.Tuple (_, es, _, _) -> walkExprs es
| SynExpr.AnonRecd (_, origExpr, flds, _) ->
(match origExpr with
| Some (e, _) -> walkExpr e
| None -> false)
|| walkExprs (List.map (fun (_, _, e) -> e) flds)
| SynExpr.Record (_, origExpr, fs, _) ->
(match origExpr with
| Some (e, _) -> walkExpr e
| None -> false)
|| (let flds = fs |> List.choose (fun (SynExprRecordField (expr = v)) -> v)
walkExprs flds)
| SynExpr.ObjExpr (bindings = bs; members = ms; extraImpls = is) ->
let bs = unionBindingAndMembers bs ms
let binds =
[
for SynInterfaceImpl (bindings = bs) in is do
yield! bs
]
walkBinds bs || walkBinds binds
| SynExpr.ForEach (_, _, _, _, _, e1, e2, _)
| SynExpr.While (_, e1, e2, _) -> walkExpr e1 || walkExpr e2
| SynExpr.For (identBody = e1; toBody = e2; doBody = e3) -> walkExpr e1 || walkExpr e2 || walkExpr e3
| SynExpr.MatchLambda (_, _, cl, _, _) -> walkMatchClauses cl
| SynExpr.Lambda (body = e) -> walkExpr e
| SynExpr.Match (expr = e; clauses = cl) -> walkExpr e || walkMatchClauses cl
| SynExpr.LetOrUse (bindings = bs; body = e) -> walkBinds bs || walkExpr e
| SynExpr.TryWith (tryExpr = e; withCases = cl) -> walkExpr e || walkMatchClauses cl
| SynExpr.TryFinally (tryExpr = e1; finallyExpr = e2) -> walkExpr e1 || walkExpr e2
| SynExpr.Sequential (_, _, e1, e2, _) -> walkExpr e1 || walkExpr e2
| SynExpr.SequentialOrImplicitYield (_, e1, e2, _, _) -> walkExpr e1 || walkExpr e2
| SynExpr.IfThenElse (ifExpr = e1; thenExpr = e2; elseExpr = e3opt) -> walkExpr e1 || walkExpr e2 || walkExprOpt e3opt
| SynExpr.IndexRange (expr1, _, expr2, _, _, _) ->
(match expr1 with
| Some e -> walkExpr e
| None -> false)
|| (match expr2 with
| Some e -> walkExpr e
| None -> false)
| SynExpr.IndexFromEnd (e, _) -> walkExpr e
| SynExpr.DotIndexedGet (e1, indexArgs, _, _) -> walkExpr e1 || walkExpr indexArgs
| SynExpr.DotIndexedSet (e1, indexArgs, e2, _, _, _) -> walkExpr e1 || walkExpr indexArgs || walkExpr e2
| SynExpr.DotNamedIndexedPropertySet (e1, _, e2, e3, _) -> walkExpr e1 || walkExpr e2 || walkExpr e3
| SynExpr.MatchBang (expr = e; clauses = cl) -> walkExpr e || walkMatchClauses cl
| SynExpr.LetOrUseBang (rhs = e1; body = e2; andBangs = es) ->
walkExpr e1
|| walkExprs
[
for SynExprAndBang (body = e) in es do
yield e
]
|| walkExpr e2
| SynExpr.InterpolatedString (parts, _, _m) ->
parts
|> List.choose (function
| SynInterpolatedStringPart.String _ -> None
| SynInterpolatedStringPart.FillExpr (x, _) -> Some x)
|> walkExprs
walkExpr inpExpr
......@@ -899,15 +974,14 @@ let (|ParsedHashDirectiveArguments|) (input: ParsedHashDirectiveArgument list) =
| ParsedHashDirectiveArgument.SourceIdentifier (_, v, _) -> v)
input
let prependIdentInLongIdentWithTrivia (SynIdent(ident, identTrivia)) dotm lid =
let prependIdentInLongIdentWithTrivia (SynIdent (ident, identTrivia)) dotm lid =
match lid with
| SynLongIdent(lid, dots, trivia) ->
SynLongIdent(ident :: lid, dotm :: dots, identTrivia :: trivia)
| SynLongIdent (lid, dots, trivia) -> SynLongIdent(ident :: lid, dotm :: dots, identTrivia :: trivia)
let mkDynamicArgExpr expr =
match expr with
| SynExpr.Ident ident ->
let con = SynConst.String (ident.idText, SynStringKind.Regular, ident.idRange)
SynExpr.Const (con, con.Range ident.idRange)
| SynExpr.Paren(expr = e) -> e
| e -> e
\ No newline at end of file
let con = SynConst.String(ident.idText, SynStringKind.Regular, ident.idRange)
SynExpr.Const(con, con.Range ident.idRange)
| SynExpr.Paren (expr = e) -> e
| e -> e
......@@ -7,21 +7,21 @@ open FSharp.Compiler.Text
[<RequireQualifiedAccess; NoEquality; NoComparison>]
type IdentTrivia =
| OriginalNotation of text: string
| OriginalNotationWithParen of leftParenRange: range * text:string * rightParenRange: range
| OriginalNotationWithParen of leftParenRange: range * text: string * rightParenRange: range
| HasParenthesis of leftParenRange: range * rightParenRange: range
[<RequireQualifiedAccess; NoEquality; NoComparison>]
type ConditionalDirectiveTrivia =
| If of expr:IfDirectiveExpression * range:range
| Else of range:range
| EndIf of range:range
| If of expr: IfDirectiveExpression * range: range
| Else of range: range
| EndIf of range: range
and [<RequireQualifiedAccess; NoEquality; NoComparison>] IfDirectiveExpression =
| And of IfDirectiveExpression * IfDirectiveExpression
| Or of IfDirectiveExpression * IfDirectiveExpression
| Not of IfDirectiveExpression
| Ident of string
[<RequireQualifiedAccess; NoEquality; NoComparison>]
type CommentTrivia =
| LineComment of range: range
......@@ -29,69 +29,92 @@ type CommentTrivia =
[<NoEquality; NoComparison>]
type ParsedImplFileInputTrivia =
{ ConditionalDirectives: ConditionalDirectiveTrivia list
CodeComments: CommentTrivia list }
{
ConditionalDirectives: ConditionalDirectiveTrivia list
CodeComments: CommentTrivia list
}
[<NoEquality; NoComparison>]
type ParsedSigFileInputTrivia =
{ ConditionalDirectives: ConditionalDirectiveTrivia list
CodeComments: CommentTrivia list }
{
ConditionalDirectives: ConditionalDirectiveTrivia list
CodeComments: CommentTrivia list
}
[<NoEquality; NoComparison>]
type SynExprTryWithTrivia =
{ TryKeyword: range
TryToWithRange: range
WithKeyword: range
WithToEndRange: range }
{
TryKeyword: range
TryToWithRange: range
WithKeyword: range
WithToEndRange: range
}
[<NoEquality; NoComparison>]
type SynExprTryFinallyTrivia =
{ TryKeyword: range
FinallyKeyword: range }
{
TryKeyword: range
FinallyKeyword: range
}
[<NoEquality; NoComparison>]
type SynExprIfThenElseTrivia =
{ IfKeyword: range
IsElif: bool
ThenKeyword: range
ElseKeyword: range option
IfToThenRange: range }
{
IfKeyword: range
IsElif: bool
ThenKeyword: range
ElseKeyword: range option
IfToThenRange: range
}
[<NoEquality; NoComparison>]
type SynExprLambdaTrivia =
{ ArrowRange: range option }
{
ArrowRange: range option
}
static member Zero: SynExprLambdaTrivia = { ArrowRange = None }
[<NoEquality; NoComparison>]
type SynExprLetOrUseTrivia =
{ InKeyword: range option }
type SynExprLetOrUseTrivia = { InKeyword: range option }
[<NoEquality; NoComparison>]
type SynExprLetOrUseBangTrivia =
{ EqualsRange: range option }
static member Zero: SynExprLetOrUseBangTrivia =
{ EqualsRange = None }
{
EqualsRange: range option
}
static member Zero: SynExprLetOrUseBangTrivia = { EqualsRange = None }
[<NoEquality; NoComparison>]
type SynExprMatchTrivia =
{ MatchKeyword: range
WithKeyword: range }
{
MatchKeyword: range
WithKeyword: range
}
[<NoEquality; NoComparison>]
type SynExprMatchBangTrivia =
{ MatchBangKeyword: range
WithKeyword: range }
{
MatchBangKeyword: range
WithKeyword: range
}
[<NoEquality; NoComparison>]
type SynMatchClauseTrivia =
{ ArrowRange: range option
BarRange: range option }
{
ArrowRange: range option
BarRange: range option
}
static member Zero: SynMatchClauseTrivia = { ArrowRange = None; BarRange = None }
[<NoEquality; NoComparison>]
type SynEnumCaseTrivia =
{ BarRange: range option
EqualsRange: range }
{
BarRange: range option
EqualsRange: range
}
[<NoEquality; NoComparison>]
type SynUnionCaseTrivia = { BarRange: range option }
......@@ -101,66 +124,109 @@ type SynPatOrTrivia = { BarRange: range }
[<NoEquality; NoComparison>]
type SynTypeDefnTrivia =
{ TypeKeyword: range option
EqualsRange: range option
WithKeyword: range option }
{
TypeKeyword: range option
EqualsRange: range option
WithKeyword: range option
}
static member Zero: SynTypeDefnTrivia =
{ TypeKeyword = None
EqualsRange = None
WithKeyword = None }
{
TypeKeyword = None
EqualsRange = None
WithKeyword = None
}
[<NoEquality; NoComparison>]
type SynBindingTrivia =
{ LetKeyword: range option
EqualsRange: range option }
{
LetKeyword: range option
EqualsRange: range option
}
static member Zero: SynBindingTrivia =
{ LetKeyword = None
EqualsRange = None }
{
LetKeyword = None
EqualsRange = None
}
[<NoEquality; NoComparison>]
type SynMemberFlagsTrivia =
{ MemberRange: range option
OverrideRange: range option
AbstractRange: range option
StaticRange: range option
DefaultRange: range option }
{
MemberRange: range option
OverrideRange: range option
AbstractRange: range option
StaticRange: range option
DefaultRange: range option
}
static member Zero: SynMemberFlagsTrivia =
{ MemberRange = None
OverrideRange = None
AbstractRange = None
StaticRange = None
DefaultRange = None }
{
MemberRange = None
OverrideRange = None
AbstractRange = None
StaticRange = None
DefaultRange = None
}
[<NoEquality; NoComparison>]
type SynExprAndBangTrivia =
{ EqualsRange: range
InKeyword: range option }
{
EqualsRange: range
InKeyword: range option
}
[<NoEquality; NoComparison>]
type SynModuleDeclNestedModuleTrivia =
{ ModuleKeyword: range option
EqualsRange: range option }
static member Zero: SynModuleDeclNestedModuleTrivia = { ModuleKeyword = None; EqualsRange = None }
{
ModuleKeyword: range option
EqualsRange: range option
}
static member Zero: SynModuleDeclNestedModuleTrivia =
{
ModuleKeyword = None
EqualsRange = None
}
[<NoEquality; NoComparison>]
type SynModuleSigDeclNestedModuleTrivia =
{ ModuleKeyword: range option
EqualsRange: range option }
static member Zero: SynModuleSigDeclNestedModuleTrivia = { ModuleKeyword = None; EqualsRange = None }
{
ModuleKeyword: range option
EqualsRange: range option
}
static member Zero: SynModuleSigDeclNestedModuleTrivia =
{
ModuleKeyword = None
EqualsRange = None
}
[<NoEquality; NoComparison>]
type SynModuleOrNamespaceTrivia =
{ ModuleKeyword: range option
NamespaceKeyword: range option }
{
ModuleKeyword: range option
NamespaceKeyword: range option
}
[<NoEquality; NoComparison>]
type SynModuleOrNamespaceSigTrivia =
{ ModuleKeyword: range option
NamespaceKeyword: range option }
{
ModuleKeyword: range option
NamespaceKeyword: range option
}
[<NoEquality; NoComparison>]
type SynValSigTrivia =
{ ValKeyword: range option
WithKeyword: range option
EqualsRange: range option }
static member Zero: SynValSigTrivia = { ValKeyword = None; WithKeyword = None; EqualsRange = None }
{
ValKeyword: range option
WithKeyword: range option
EqualsRange: range option
}
static member Zero: SynValSigTrivia =
{
ValKeyword = None
WithKeyword = None
EqualsRange = None
}
......@@ -22,13 +22,15 @@ type XmlDoc(unprocessedLines: string[], range: range) =
match lines with
| [] -> []
| lineA :: rest as lines ->
let lineAT = lineA.TrimStart([|' '|])
if lineAT = "" then processLines rest
elif lineAT.StartsWithOrdinal("<") then lines
let lineAT = lineA.TrimStart([| ' ' |])
if lineAT = "" then
processLines rest
elif lineAT.StartsWithOrdinal("<") then
lines
else
["<summary>"] @
(lines |> List.map Internal.Utilities.XmlAdapters.escape) @
["</summary>"]
[ "<summary>" ]
@ (lines |> List.map Internal.Utilities.XmlAdapters.escape) @ [ "</summary>" ]
/// Get the lines before insertion of implicit summary tags and encoding
member _.UnprocessedLines = unprocessedLines
......@@ -45,13 +47,12 @@ type XmlDoc(unprocessedLines: string[], range: range) =
static member Empty = XmlDocStatics.Empty
member _.IsEmpty =
unprocessedLines |> Array.forall String.IsNullOrWhiteSpace
member _.IsEmpty = unprocessedLines |> Array.forall String.IsNullOrWhiteSpace
member doc.NonEmpty = not doc.IsEmpty
static member Merge (doc1: XmlDoc) (doc2: XmlDoc) =
let range =
let range =
if doc1.IsEmpty then doc2.Range
elif doc2.IsEmpty then doc1.Range
else unionRanges doc1.Range doc2.Range
......@@ -59,17 +60,16 @@ type XmlDoc(unprocessedLines: string[], range: range) =
XmlDoc(Array.append doc1.UnprocessedLines doc2.UnprocessedLines, range)
member doc.GetXmlText() =
if doc.IsEmpty then ""
if doc.IsEmpty then
""
else
doc.GetElaboratedXmlLines()
|> String.concat Environment.NewLine
doc.GetElaboratedXmlLines() |> String.concat Environment.NewLine
member doc.Check(paramNamesOpt: string list option) =
try
// We must wrap with <doc> in order to have only one root element
let xml =
XDocument.Parse("<doc>\n"+doc.GetXmlText()+"\n</doc>",
LoadOptions.SetLineInfo ||| LoadOptions.PreserveWhitespace)
XDocument.Parse("<doc>\n" + doc.GetXmlText() + "\n</doc>", LoadOptions.SetLineInfo ||| LoadOptions.PreserveWhitespace)
// The parameter names are checked for consistency, so parameter references and
// parameter documentation must match an actual parameter. In addition, if any parameters
......@@ -79,93 +79,115 @@ type XmlDoc(unprocessedLines: string[], range: range) =
| Some paramNames ->
for p in xml.Descendants(XName.op_Implicit "param") do
match p.Attribute(XName.op_Implicit "name") with
| null ->
warning (Error (FSComp.SR.xmlDocMissingParameterName(), doc.Range))
| null -> warning (Error(FSComp.SR.xmlDocMissingParameterName (), doc.Range))
| attr ->
let nm = attr.Value
if not (paramNames |> List.contains nm) then
warning (Error (FSComp.SR.xmlDocInvalidParameterName(nm), doc.Range))
warning (Error(FSComp.SR.xmlDocInvalidParameterName (nm), doc.Range))
let paramsWithDocs =
[ for p in xml.Descendants(XName.op_Implicit "param") do
match p.Attribute(XName.op_Implicit "name") with
| null -> ()
| attr -> attr.Value ]
[
for p in xml.Descendants(XName.op_Implicit "param") do
match p.Attribute(XName.op_Implicit "name") with
| null -> ()
| attr -> attr.Value
]
if paramsWithDocs.Length > 0 then
for p in paramNames do
if not (paramsWithDocs |> List.contains p) then
warning (Error (FSComp.SR.xmlDocMissingParameter(p), doc.Range))
warning (Error(FSComp.SR.xmlDocMissingParameter (p), doc.Range))
let duplicates = paramsWithDocs |> List.duplicates
for d in duplicates do
warning (Error (FSComp.SR.xmlDocDuplicateParameter(d), doc.Range))
warning (Error(FSComp.SR.xmlDocDuplicateParameter (d), doc.Range))
for pref in xml.Descendants(XName.op_Implicit "paramref") do
match pref.Attribute(XName.op_Implicit "name") with
| null -> warning (Error (FSComp.SR.xmlDocMissingParameterName(), doc.Range))
| null -> warning (Error(FSComp.SR.xmlDocMissingParameterName (), doc.Range))
| attr ->
let nm = attr.Value
if not (paramNames |> List.contains nm) then
warning (Error (FSComp.SR.xmlDocInvalidParameterName(nm), doc.Range))
warning (Error(FSComp.SR.xmlDocInvalidParameterName (nm), doc.Range))
with e ->
warning (Error (FSComp.SR.xmlDocBadlyFormed(e.Message), doc.Range))
warning (Error(FSComp.SR.xmlDocBadlyFormed (e.Message), doc.Range))
#if CREF_ELABORATION
member doc.Elaborate (crefResolver) =
for see in seq { yield! xml.Descendants(XName.op_Implicit "see")
yield! xml.Descendants(XName.op_Implicit "seealso")
yield! xml.Descendants(XName.op_Implicit "exception") } do
match see.Attribute(XName.op_Implicit "cref") with
| null -> warning (Error (FSComp.SR.xmlDocMissingCrossReference(), doc.Range))
| attr ->
let cref = attr.Value
if cref.StartsWith("T:") || cref.StartsWith("P:") || cref.StartsWith("M:") ||
cref.StartsWith("E:") || cref.StartsWith("F:") then
()
else
match crefResolver cref with
| None ->
warning (Error (FSComp.SR.xmlDocUnresolvedCrossReference(nm), doc.Range))
| Some text ->
attr.Value <- text
modified <- true
if modified then
let m = doc.Range
let newLines =
[| for e in xml.Elements() do
yield! e.ToString().Split([| '\r'; '\n' |], StringSplitOptions.RemoveEmptyEntries) |]
lines <- newLines
member doc.Elaborate(crefResolver) =
for see in
seq {
yield! xml.Descendants(XName.op_Implicit "see")
yield! xml.Descendants(XName.op_Implicit "seealso")
yield! xml.Descendants(XName.op_Implicit "exception")
} do
match see.Attribute(XName.op_Implicit "cref") with
| null -> warning (Error(FSComp.SR.xmlDocMissingCrossReference (), doc.Range))
| attr ->
let cref = attr.Value
if
cref.StartsWith("T:")
|| cref.StartsWith("P:")
|| cref.StartsWith("M:")
|| cref.StartsWith("E:")
|| cref.StartsWith("F:")
then
()
else
match crefResolver cref with
| None -> warning (Error(FSComp.SR.xmlDocUnresolvedCrossReference (nm), doc.Range))
| Some text ->
attr.Value <- text
modified <- true
if modified then
let m = doc.Range
let newLines =
[|
for e in xml.Elements() do
yield! e.ToString().Split([| '\r'; '\n' |], StringSplitOptions.RemoveEmptyEntries)
|]
lines <- newLines
#endif
// Discriminated unions can't contain statics, so we use a separate type
and XmlDocStatics() =
static let empty = XmlDoc ([| |], range0)
static let empty = XmlDoc([||], range0)
static member Empty = empty
/// Used to collect XML documentation during lexing and parsing.
type XmlDocCollector() =
let mutable savedLines = ResizeArray<string * range>()
let mutable savedGrabPoints = Dictionary<pos, struct(int * int * bool)>()
let mutable savedGrabPoints = Dictionary<pos, struct (int * int * bool)>()
let mutable currentGrabPointCommentsCount = 0
let mutable delayedGrabPoint = ValueNone
member _.AddGrabPoint(pos: pos) =
if currentGrabPointCommentsCount = 0 then () else
let xmlDocBlock = struct(savedLines.Count - currentGrabPointCommentsCount, savedLines.Count - 1, false)
savedGrabPoints.Add(pos, xmlDocBlock)
currentGrabPointCommentsCount <- 0
delayedGrabPoint <- ValueNone
if currentGrabPointCommentsCount = 0 then
()
else
let xmlDocBlock =
struct (savedLines.Count - currentGrabPointCommentsCount, savedLines.Count - 1, false)
savedGrabPoints.Add(pos, xmlDocBlock)
currentGrabPointCommentsCount <- 0
delayedGrabPoint <- ValueNone
member _.AddGrabPointDelayed(pos: pos) =
if currentGrabPointCommentsCount = 0 then () else
match delayedGrabPoint with
| ValueNone -> delayedGrabPoint <- ValueSome(pos)
| _ -> ()
if currentGrabPointCommentsCount = 0 then
()
else
match delayedGrabPoint with
| ValueNone -> delayedGrabPoint <- ValueSome(pos)
| _ -> ()
member x.AddXmlDocLine(line, range) =
match delayedGrabPoint with
......@@ -177,16 +199,18 @@ type XmlDocCollector() =
member _.LinesBefore grabPointPos =
match savedGrabPoints.TryGetValue grabPointPos with
| true, struct(startIndex, endIndex, _) ->
| true, struct (startIndex, endIndex, _) ->
let linesBefore = Array.create (endIndex - startIndex + 1) ("", range0)
for i in startIndex .. endIndex do
for i in startIndex..endIndex do
linesBefore[i - startIndex] <- savedLines[i]
linesBefore
| false, _ -> [||]
member _.LinesRange grabPointPos =
match savedGrabPoints.TryGetValue grabPointPos with
| true, struct(startIndex, endIndex, _) ->
| true, struct (startIndex, endIndex, _) ->
let startRange = savedLines[startIndex] |> snd
let endRange = savedLines[endIndex] |> snd
unionRanges startRange endRange
......@@ -194,8 +218,7 @@ type XmlDocCollector() =
member _.SetXmlDocValidity(grabPointPos, isValid) =
match savedGrabPoints.TryGetValue grabPointPos with
| true, struct(startIndex, endIndex, _) ->
savedGrabPoints[grabPointPos] <- struct(startIndex, endIndex, isValid)
| true, struct (startIndex, endIndex, _) -> savedGrabPoints[grabPointPos] <- struct (startIndex, endIndex, isValid)
| _ -> ()
member _.HasComments grabPointPos =
......@@ -205,13 +228,16 @@ type XmlDocCollector() =
let comments = ResizeArray<range>(savedLines.Count)
for startIndex, endIndex, isValid in savedGrabPoints.Values do
if isValid then () else
let _, startRange = savedLines[startIndex]
let _, endRange = savedLines[endIndex]
let range = unionRanges startRange endRange
informationalWarning (Error(FSComp.SR.invalidXmlDocPosition(), range))
// Collect invalid triple slash comment ranges, to later transform these to trivia
[ startIndex .. endIndex ] |> List.iter (fun idx -> savedLines[idx] |> snd |> comments.Add)
if isValid then
()
else
let _, startRange = savedLines[startIndex]
let _, endRange = savedLines[endIndex]
let range = unionRanges startRange endRange
informationalWarning (Error(FSComp.SR.invalidXmlDocPosition (), range))
// Collect invalid triple slash comment ranges, to later transform these to trivia
[ startIndex..endIndex ]
|> List.iter (fun idx -> savedLines[idx] |> snd |> comments.Add)
List.ofSeq comments
......@@ -224,28 +250,25 @@ type PreXmlDoc =
member x.ToXmlDoc(check: bool, paramNamesOpt: string list option) =
match x with
| PreXmlDirect (lines, m) ->
XmlDoc(lines, m)
| PreXmlMerge(a, b) ->
XmlDoc.Merge (a.ToXmlDoc(check, paramNamesOpt)) (b.ToXmlDoc(check, paramNamesOpt))
| PreXmlDocEmpty ->
XmlDoc.Empty
| PreXmlDirect (lines, m) -> XmlDoc(lines, m)
| PreXmlMerge (a, b) -> XmlDoc.Merge (a.ToXmlDoc(check, paramNamesOpt)) (b.ToXmlDoc(check, paramNamesOpt))
| PreXmlDocEmpty -> XmlDoc.Empty
| PreXmlDoc (pos, collector) ->
let preLines = collector.LinesBefore pos
if preLines.Length = 0 then
XmlDoc.Empty
else
let lines = Array.map fst preLines
let m = Array.reduce unionRanges (Array.map snd preLines)
let doc = XmlDoc (lines, m)
if check then
doc.Check(paramNamesOpt)
let doc = XmlDoc(lines, m)
if check then doc.Check(paramNamesOpt)
doc
member internal x.Range =
match x with
| PreXmlDirect (_, m) -> m
| PreXmlMerge(part1, part2) ->
| PreXmlMerge (part1, part2) ->
if part1.IsEmpty then part2.Range
elif part2.IsEmpty then part1.Range
else unionRanges part1.Range part2.Range
......@@ -255,7 +278,7 @@ type PreXmlDoc =
member x.IsEmpty =
match x with
| PreXmlDirect (lines, _) -> lines |> Array.forall String.IsNullOrWhiteSpace
| PreXmlMerge(a, b) -> a.IsEmpty && b.IsEmpty
| PreXmlMerge (a, b) -> a.IsEmpty && b.IsEmpty
| PreXmlDocEmpty -> true
| PreXmlDoc (pos, collector) -> not (collector.HasComments pos)
......@@ -272,7 +295,7 @@ type PreXmlDoc =
static member Create(unprocessedLines, range) = PreXmlDirect(unprocessedLines, range)
static member Merge a b = PreXmlMerge (a, b)
static member Merge a b = PreXmlMerge(a, b)
[<Sealed>]
type XmlDocumentationInfo private (tryGetXmlDocument: unit -> XmlDocument option) =
......@@ -280,17 +303,22 @@ type XmlDocumentationInfo private (tryGetXmlDocument: unit -> XmlDocument option
// 2 and 4 are arbitrary but should be reasonable enough
[<Literal>]
static let cacheStrongSize = 2
[<Literal>]
static let cacheMaxSize = 4
static let cacheAreSimilar ((str1: string, dt1: DateTime), (str2: string, dt2: DateTime)) =
str1.Equals(str2, StringComparison.OrdinalIgnoreCase) &&
dt1 = dt2
str1.Equals(str2, StringComparison.OrdinalIgnoreCase) && dt1 = dt2
static let cache = AgedLookup<unit, string * DateTime, XmlDocument>(keepStrongly=cacheStrongSize, areSimilar=cacheAreSimilar, keepMax=cacheMaxSize)
static let cache =
AgedLookup<unit, string * DateTime, XmlDocument>(
keepStrongly = cacheStrongSize,
areSimilar = cacheAreSimilar,
keepMax = cacheMaxSize
)
let tryGetSummaryNode xmlDocSig =
tryGetXmlDocument()
tryGetXmlDocument ()
|> Option.bind (fun doc ->
match doc.SelectSingleNode(sprintf "doc/members/member[@name='%s']" xmlDocSig) with
| null -> None
......@@ -302,20 +330,25 @@ type XmlDocumentationInfo private (tryGetXmlDocument: unit -> XmlDocument option
|> Option.map (fun node ->
let childNodes = node.ChildNodes
let lines = Array.zeroCreate childNodes.Count
for i = 0 to childNodes.Count - 1 do
let childNode = childNodes[i]
lines[i] <- childNode.OuterXml
XmlDoc(lines, range0)
)
XmlDoc(lines, range0))
static member TryCreateFromFile(xmlFileName: string) =
if not (FileSystem.FileExistsShim(xmlFileName)) || not (String.Equals(Path.GetExtension(xmlFileName), ".xml", StringComparison.OrdinalIgnoreCase)) then
if
not (FileSystem.FileExistsShim(xmlFileName))
|| not (String.Equals(Path.GetExtension(xmlFileName), ".xml", StringComparison.OrdinalIgnoreCase))
then
None
else
let tryGetXmlDocument () =
try
let lastWriteTime = FileSystem.GetLastWriteTimeShim(xmlFileName)
let cacheKey = (xmlFileName, lastWriteTime)
match cache.TryGet((), cacheKey) with
| Some doc -> Some doc
| _ ->
......@@ -326,6 +359,7 @@ type XmlDocumentationInfo private (tryGetXmlDocument: unit -> XmlDocument option
Some doc
with _ ->
None
Some(XmlDocumentationInfo(tryGetXmlDocument))
type IXmlDocumentationInfoLoader =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册