Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,12 @@
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\ExternalSymbol.fs">
<Link>Service/ExternalSymbol.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\QuickParse.fsi">
<Link>Service/QuickParse.fsi</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\QuickParse.fs">
<Link>Service/QuickParse.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\service.fsi">
<Link>Service/service.fsi</Link>
Expand Down
6 changes: 6 additions & 0 deletions fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,12 @@
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\ExternalSymbol.fs">
<Link>Service/ExternalSymbol.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\QuickParse.fsi">
<Link>Service/QuickParse.fsi</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\QuickParse.fs">
<Link>Service/QuickParse.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\service.fsi">
<Link>Service/service.fsi</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,12 @@
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\ExternalSymbol.fs">
<Link>Service/ExternalSymbol.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\QuickParse.fsi">
<Link>Service/QuickParse.fsi</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\QuickParse.fs">
<Link>Service/QuickParse.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)\fsharp\vs\service.fsi">
<Link>Service/service.fsi</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,12 @@
<Compile Include="..\vs\ExternalSymbol.fs">
<Link>Service/ExternalSymbol.fs</Link>
</Compile>
<Compile Include="..\vs\QuickParse.fsi">
<Link>Service/QuickParse.fsi</Link>
</Compile>
<Compile Include="..\vs\QuickParse.fs">
<Link>Service/QuickParse.fs</Link>
</Compile>
<Compile Include="..\vs\service.fsi">
<Link>Service/service.fsi</Link>
</Compile>
Expand Down

Large diffs are not rendered by default.

90 changes: 90 additions & 0 deletions src/fsharp/vs/QuickParse.fsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace Microsoft.FSharp.Compiler

open System
open Microsoft.FSharp.Compiler.SourceCodeServices

/// Qualified long name.
#if COMPILER_PUBLIC_API
type PartialLongName =
#else
type internal PartialLongName =
#endif
{ /// Qualifying idents, prior to the last dot, not including the last part.
QualifyingIdents: string list

/// Last part of long ident.
PartialIdent: string

/// The column number at the end of full partial name.
EndColumn: int

/// Position of the last dot.
LastDotPos: int option }

/// Empty patial long name.
static member Empty: endColumn: int -> PartialLongName

/// Methods for cheaply and innacurately parsing F#.
///
/// These methods are very old and are mostly to do with extracting "long identifier islands"
/// A.B.C
/// from F# source code, an approach taken from pre-F# VS samples for implementing intelliense.
///
/// This code should really no longer be needed since the language service has access to
/// parsed F# source code ASTs. However, the long identifiers are still passed back to GetDeclarations and friends in the
/// F# Compiler Service and it's annoyingly hard to remove their use completely.
///
/// In general it is unlikely much progress will be made by fixing this code - it will be better to
/// extract more information from the F# ASTs.
///
/// It's also surprising how hard even the job of getting long identifier islands can be. For example the code
/// below is inaccurate for long identifier chains involving ``...`` identifiers. And there are special cases
/// for active pattern names and so on.
#if COMPILER_PUBLIC_API
module QuickParse =
#else
module internal QuickParse =
#endif
/// Puts us after the last character.
val MagicalAdjustmentConstant : int

// Adjusts the token tag for the given identifier
// - if we're inside active pattern name (at the bar), correct the token TAG to be an identifier
val CorrectIdentifierToken : tokenText: string -> tokenTag: int -> int

/// Given a string and a position in that string, find an identifier as
/// expected by `GotoDefinition`. This will work when the cursor is
/// immediately before the identifier, within the identifier, or immediately
/// after the identifier.
///
/// 'tolerateJustAfter' indicates that we tolerate being one character after the identifier, used
/// for goto-definition
///
/// In general, only identifiers composed from upper/lower letters and '.' are supported, but there
/// are a couple of explicitly handled exceptions to allow some common scenarios:
/// - When the name contains only letters and '|' symbol, it may be an active pattern, so we
/// treat it as a valid identifier - e.g. let ( |Identitiy| ) a = a
/// (but other identifiers that include '|' are not allowed - e.g. '||' operator)
/// - It searches for double tick (``) to see if the identifier could be something like ``a b``
///
/// REVIEW: Also support, e.g., operators, performing the necessary mangling.
/// (i.e., I would like that the name returned here can be passed as-is
/// (post `.`-chopping) to `GetDeclarationLocation.)
///
/// In addition, return the position where a `.` would go if we were making
/// a call to `DeclItemsForNamesAtPosition` for intellisense. This will
/// allow us to use find the correct qualified items rather than resorting
/// to the more expensive and less accurate environment lookup.
val GetCompleteIdentifierIsland : tolerateJustAfter: bool -> tokenText: string -> index: int -> (string * int * bool) option

/// Get the partial long name of the identifier to the left of index.
val GetPartialLongName : lineStr: string * index: int -> (string list * string)

/// Get the partial long name of the identifier to the left of index.
/// For example, for `System.DateTime.Now` it returns PartialLongName ([|"System"; "DateTime"|], "Now", Some 32), where "32" pos of the last dot.
val GetPartialLongNameEx : lineStr: string * index: int -> PartialLongName

/// Tests whether the user is typing something like "member x." or "override (*comment*) x."
val TestMemberOrOverrideDeclaration : tokens: FSharpTokenInfo[] -> bool
Loading