Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,47 @@ type internal TypeCheckInfo
|> List.prependIfSome (CreateCompletionItemForSuggestedPatternName caseIdPos fieldName))
|> Option.defaultValue completions

/// Gets all methods that a type can override, but has not yet done so.
let GetOverridableMethods pos typeNameRange =
let isMethodOverridable alreadyOverridden (candidate: MethInfo) =
not candidate.IsFinal
&& not (
alreadyOverridden
|> List.exists (MethInfosEquivByNameAndSig EraseNone true g amap range0 candidate)
)

let (nenv, ad), m = GetBestEnvForPos pos

sResolutions.CapturedNameResolutions
|> ResizeArray.tryPick (fun r ->
match r.Item with
| Item.Types (_, ty :: _) when equals r.Range typeNameRange && isAppTy g ty ->
let superTy =
(tcrefOfAppTy g ty).TypeContents.tcaug_super |> Option.defaultValue g.obj_ty

let overriddenMethods =
GetImmediateIntrinsicMethInfosOfType (None, ad) g amap typeNameRange ty
|> List.filter (fun x -> x.IsDefiniteFSharpOverride)

let overridableMethods =
GetIntrinsicMethInfosOfType
infoReader
None
ad
TypeHierarchy.AllowMultiIntfInstantiations.No
FindMemberFlag.PreferOverrides
range0
superTy
|> List.filter (isMethodOverridable overriddenMethods)
|> List.groupBy (fun x -> x.DisplayName)
|> List.map (fun (name, overloads) ->
Item.MethodGroup(name, overloads, None)
|> ItemWithNoInst
|> CompletionItem ValueNone ValueNone)

Some(overridableMethods, nenv.DisplayEnv, m)
| _ -> None)

let getItem (x: ItemWithInst) = x.Item

let GetDeclaredItems
Expand Down Expand Up @@ -1559,6 +1600,8 @@ type internal TypeCheckInfo
| _ -> None)
|> Option.orElse declaredItems

| Some (CompletionContext.MethodOverride enclosingTypeNameRange) -> GetOverridableMethods pos enclosingTypeNameRange

// Other completions
| cc ->
match residueOpt |> Option.bind Seq.tryHead with
Expand Down Expand Up @@ -1664,7 +1707,10 @@ type internal TypeCheckInfo
|> Option.map (fun parsedInput ->
ParsedInput.GetFullNameOfSmallestModuleOrNamespaceAtPoint(mkPos line 0, parsedInput))

let isAttributeApplication = ctx = Some CompletionContext.AttributeApplication
let isAttributeApplication =
match ctx with
| Some CompletionContext.AttributeApplication -> true
| _ -> false

DeclarationListInfo.Create(
infoReader,
Expand Down
35 changes: 34 additions & 1 deletion src/Compiler/Service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ open System.Text.RegularExpressions
open Internal.Utilities.Library
open FSharp.Compiler.Diagnostics
open FSharp.Compiler.Syntax
open FSharp.Compiler.SyntaxTrivia
open FSharp.Compiler.Syntax.PrettyNaming
open FSharp.Compiler.SyntaxTreeOps
open FSharp.Compiler.Text
Expand Down Expand Up @@ -97,6 +98,9 @@ type CompletionContext =
/// Completing a pattern in a match clause, member/let binding or lambda
| Pattern of context: PatternContext

/// Completing a method override (e.g. override this.ToStr|)
| MethodOverride of enclosingTypeNameRange: range

type ShortIdent = string

type ShortIdents = ShortIdent[]
Expand Down Expand Up @@ -1414,9 +1418,36 @@ module ParsedInput =

| _ -> None

member _.VisitBinding(_, defaultTraverse, (SynBinding (headPat = headPat) as synBinding)) =
member _.VisitBinding(path, defaultTraverse, (SynBinding (headPat = headPat; trivia = trivia) as synBinding)) =

let isOverride leadingKeyword =
match leadingKeyword with
| SynLeadingKeyword.Override _ -> true
| _ -> false

let overrideContext path =
match path with
| _ :: SyntaxNode.SynTypeDefn (SynTypeDefn(typeInfo = SynComponentInfo(longId = [ enclosingType ]))) :: _ ->
Some(CompletionContext.MethodOverride enclosingType.idRange)
| _ -> Some CompletionContext.Invalid

match headPat with

// override _.|
| SynPat.FromParseError _ when isOverride trivia.LeadingKeyword -> overrideContext path

// override this.|
| SynPat.Named(ident = SynIdent (ident = selfId)) when
isOverride trivia.LeadingKeyword && selfId.idRange.End.IsAdjacentTo pos
->
overrideContext path

// override this.ToStr|
| SynPat.LongIdent(longDotId = SynLongIdent(id = [ _; methodId ])) when
isOverride trivia.LeadingKeyword && rangeContainsPos methodId.idRange pos
->
overrideContext path

| SynPat.LongIdent (longDotId = lidwd; argPats = SynArgPats.Pats pats; range = m) when rangeContainsPos m pos ->
if rangeContainsPos lidwd.Range pos then
// let fo|o x = ()
Expand All @@ -1425,10 +1456,12 @@ module ParsedInput =
pats
|> List.tryPick (fun pat -> TryGetCompletionContextInPattern true pat None pos)
|> Option.orElseWith (fun () -> defaultTraverse synBinding)

| SynPat.Named (range = range)
| SynPat.As (_, SynPat.Named (range = range), _) when rangeContainsPos range pos ->
// let fo|o = 1
Some CompletionContext.Invalid

| _ -> defaultTraverse synBinding

member _.VisitHashDirective(_, _directive, range) =
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Service/ServiceParsedInputOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ type public CompletionContext =
/// Completing a pattern in a match clause, member/let binding or lambda
| Pattern of context: PatternContext

/// Completing a method override (e.g. override this.ToStr|)
| MethodOverride of enclosingTypeNameRange: range

type public ModuleKind =
{ IsAutoOpen: bool
HasModuleSuffix: bool }
Expand Down
Loading