Skip to content

Commit

Permalink
Add extern keyword to SynBindingTrivia. (#14030)
Browse files Browse the repository at this point in the history
  • Loading branch information
nojaf authored Oct 6, 2022
1 parent e389d77 commit 23d9352
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 8 deletions.
3 changes: 3 additions & 0 deletions src/Compiler/SyntaxTree/ParseHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ let mkSynMemberDefnGetSet
{
LetKeyword = None
EqualsRange = mEquals
ExternKeyword = None
}

let binding =
Expand Down Expand Up @@ -542,6 +543,7 @@ let mkSynMemberDefnGetSet
{
LetKeyword = None
EqualsRange = mEquals
ExternKeyword = None
}

let binding =
Expand Down Expand Up @@ -629,6 +631,7 @@ let mkSynMemberDefnGetSet
{
LetKeyword = None
EqualsRange = mEquals
ExternKeyword = None
}

let bindingOuter =
Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fs
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,14 @@ type SynTypeDefnSigTrivia =
type SynBindingTrivia =
{
LetKeyword: range option
ExternKeyword: range option
EqualsRange: range option
}

static member Zero: SynBindingTrivia =
{
LetKeyword = None
ExternKeyword = None
EqualsRange = None
}

Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ type SynBindingTrivia =
/// The syntax range of the `let` keyword.
LetKeyword: range option

/// The syntax range of the `extern` keyword.
ExternKeyword: range option

/// The syntax range of the `=` token.
EqualsRange: range option
}
Expand Down
16 changes: 9 additions & 7 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -1868,7 +1868,7 @@ memberCore:
let xmlDoc = grabXmlDocAtRangeStart(parseState, attrs, rangeStart)
let memberFlags = Some (memFlagsBuilder SynMemberKind.Member)
let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range)
let trivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals }
let trivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals; ExternKeyword = None }
let binding = mkSynBinding (xmlDoc, bindingPat) (vis, $1, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, optReturnType, $5, mRhs, [], attrs, memberFlags, trivia)
let memberRange = unionRanges rangeStart mRhs |> unionRangeWithXmlDoc xmlDoc
[ SynMemberDefn.Member (binding, memberRange) ]) }
Expand Down Expand Up @@ -1985,7 +1985,7 @@ classDefnMember:
let declPat = SynPat.LongIdent (SynLongIdent([mkSynId (rhs parseState 3) "new"], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [$4], vis, rhs parseState 3)
// Check that 'SynPatForConstructorDecl' matches this correctly
assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false)
let synBindingTrivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals }
let synBindingTrivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals; ExternKeyword = None }
[ SynMemberDefn.Member(SynBinding (None, SynBindingKind.Normal, false, false, $1, xmlDoc, valSynData, declPat, None, expr, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, synBindingTrivia), m) ] }

| opt_attributes opt_declVisibility STATIC typeKeyword tyconDefn
Expand Down Expand Up @@ -2743,7 +2743,8 @@ hardwhiteDefnBindingsTerminator:
/* An 'extern' DllImport function definition in C-style syntax */
cPrototype:
| EXTERN cRetType opt_access ident opt_HIGH_PRECEDENCE_APP LPAREN externArgs rparen
{ let rty, vis, nm, args = $2, $3, $4, $7
{ let mExtern = rhs parseState 1
let rty, vis, nm, args = $2, $3, $4, $7
let nmm = rhs parseState 3
let argsm = rhs parseState 6
let mBindLhs = lhs parseState
Expand All @@ -2760,10 +2761,11 @@ cPrototype:
let bindingPat = SynPat.LongIdent (SynLongIdent([nm], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [SynPat.Tuple(false, args, argsm)], vis, nmm)
let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range)
let xmlDoc = grabXmlDoc(parseState, attrs, 1)
let trivia = { LetKeyword = None; ExternKeyword = Some mExtern; EqualsRange = None }
let binding =
mkSynBinding
(xmlDoc, bindingPat)
(vis, false, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, Some rty, rhsExpr, mRhs, [], attrs, None, SynBindingTrivia.Zero)
(vis, false, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, Some rty, rhsExpr, mRhs, [], attrs, None, trivia)
[], [binding]) }

/* A list of arguments in an 'extern' DllImport function definition */
Expand Down Expand Up @@ -2882,7 +2884,7 @@ localBinding:
let mWhole = (unionRanges mLetKwd mRhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range)
let spBind = if IsDebugPointBinding bindingPat expr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet
let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range)
let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals }
let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals; ExternKeyword = None }
mkSynBinding (xmlDoc, bindingPat) (vis, $1, $2, mWholeBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None, trivia))
localBindingRange, localBindingBuilder }

Expand All @@ -2897,7 +2899,7 @@ localBinding:
let zeroWidthAtEnd = mEquals.EndRange
let rhsExpr = arbExpr("localBinding1", zeroWidthAtEnd)
let spBind = if IsDebugPointBinding bindingPat rhsExpr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet
let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals }
let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals; ExternKeyword = None }
mkSynBinding (xmlDoc, bindingPat) (vis, $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia))
mWhole, localBindingBuilder }

Expand All @@ -2910,7 +2912,7 @@ localBinding:
let localBindingBuilder =
(fun xmlDoc attrs vis mLetKwd ->
let spBind = DebugPointAtBinding.Yes (unionRanges mLetKwd mRhs)
let trivia = { LetKeyword = Some mLetKwd; EqualsRange = None }
let trivia = { LetKeyword = Some mLetKwd; EqualsRange = None; ExternKeyword = None }
let rhsExpr = arbExpr("localBinding2", mRhs)
mkSynBinding (xmlDoc, bindingPat) (vis, $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia))
mWhole, localBindingBuilder }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@
<Compile Include="..\service\SyntaxTreeTests\AttributeTests.fs">
<Link>SyntaxTree\AttributeTests.fs</Link>
</Compile>
<Compile Include="..\service\SyntaxTreeTests\ExternTests.fs">
<Link>SyntaxTree\ExternTests.fs</Link>
</Compile>
<Compile Include="..\service\FileSystemTests.fs">
<Link>FileSystemTests.fs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9419,11 +9419,13 @@ FSharp.Compiler.SyntaxTrivia.SynBindingTrivia
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia Zero
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia get_Zero()
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] EqualsRange
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] ExternKeyword
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] LetKeyword
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_EqualsRange()
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_ExternKeyword()
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_LetKeyword()
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: System.String ToString()
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range])
FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia
FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: FSharp.Compiler.Text.Range EqualsRange
FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: FSharp.Compiler.Text.Range get_EqualsRange()
Expand Down
21 changes: 21 additions & 0 deletions tests/service/SyntaxTreeTests/ExternTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module FSharp.Compiler.Service.Tests.SyntaxTreeTests.ExternTests

open FSharp.Compiler.Service.Tests.Common
open FSharp.Compiler.Syntax
open FSharp.Compiler.SyntaxTrivia
open NUnit.Framework

[<Test>]
let ``extern keyword is present in trivia`` () =
let parseResults = getParseResults "extern void GetProcessHeap()"

match parseResults with
| ParsedInput.ImplFile(ParsedImplFileInput(contents = [
SynModuleOrNamespace.SynModuleOrNamespace(decls = [
SynModuleDecl.Let(bindings = [
SynBinding(trivia = { ExternKeyword = Some mExtern })
])
])
])) ->
assertRange (1, 0) (1, 6) mExtern
| _ -> Assert.Fail $"Could not get valid AST, got {parseResults}"

0 comments on commit 23d9352

Please sign in to comment.