diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md index 655ad02ad2a..226914e6c8d 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -9,6 +9,8 @@ ### Added +* Add FSharpCodeCompletionOptions ([PR #19030](https://github.com/dotnet/fsharp/pull/19030)) + ### Changed * Parallel compilation stabilised and enabled by default ([PR #18998](https://github.com/dotnet/fsharp/pull/18998)) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 8df68aa0e2e..3b9d0722133 100755 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -478,13 +478,11 @@ let CheckFSharpAttributesForObsolete (g:TcGlobals) attribs = // like Span and ReadOnlySpan in completion lists due to their dual attributes. not (HasFSharpAttributeOpt g g.attrib_IsByRefLikeAttribute_opt attribs) -/// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. -/// Also check the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows -/// items to be suppressed from intellisense. -let CheckFSharpAttributesForUnseen g attribs _m = +/// Indicates if a list of F# attributes contains 'ObsoleteAttribute' or CompilerMessageAttribute', which has an IsHidden argument +/// May be used to suppress items from intellisense. +let CheckFSharpAttributesForUnseen g attribs _m allowObsolete = not (isNil attribs) && - (CheckFSharpAttributesForObsolete g attribs || - CheckFSharpAttributesForHidden g attribs) + (not allowObsolete && CheckFSharpAttributesForObsolete g attribs || CheckFSharpAttributesForHidden g attribs) #if !NO_TYPEPROVIDERS /// Indicate if a list of provided attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. @@ -577,13 +575,13 @@ let CheckMethInfoAttributes g m tyargsOpt (minfo: MethInfo) = /// Indicate if a method has 'Obsolete', 'CompilerMessageAttribute' or 'TypeProviderEditorHideMethodsAttribute'. /// Used to suppress the item in intellisense. -let MethInfoIsUnseen g (m: range) (ty: TType) minfo = - let isUnseenByObsoleteAttrib () = +let MethInfoIsUnseen g (m: range) (ty: TType) minfo allowObsolete = + let isUnseenByObsoleteAttrib () = match BindMethInfoAttributes m minfo - (fun ilAttribs -> Some(CheckILAttributesForUnseen g ilAttribs m)) - (fun fsAttribs -> Some(CheckFSharpAttributesForUnseen g fsAttribs m)) + (fun ilAttribs -> Some(not allowObsolete && CheckILAttributesForUnseen g ilAttribs m)) + (fun fsAttribs -> Some(CheckFSharpAttributesForUnseen g fsAttribs m allowObsolete)) #if !NO_TYPEPROVIDERS - (fun provAttribs -> Some(CheckProvidedAttributesForUnseen provAttribs m)) + (fun provAttribs -> Some(not allowObsolete && CheckProvidedAttributesForUnseen provAttribs m)) #else (fun _provAttribs -> None) #endif @@ -620,14 +618,14 @@ let MethInfoIsUnseen g (m: range) (ty: TType) minfo = /// Indicate if a property has 'Obsolete' or 'CompilerMessageAttribute'. /// Used to suppress the item in intellisense. -let PropInfoIsUnseen m pinfo = +let PropInfoIsUnseen m allowObsolete pinfo = match pinfo with | ILProp (ILPropInfo(_, pdef) as ilpinfo) -> // Properties on .NET tuple types are resolvable but unseen isAnyTupleTy pinfo.TcGlobals ilpinfo.ILTypeInfo.ToType || CheckILAttributesForUnseen pinfo.TcGlobals pdef.CustomAttrs m | FSProp (g, _, Some vref, _) - | FSProp (g, _, _, Some vref) -> CheckFSharpAttributesForUnseen g vref.Attribs m + | FSProp (g, _, _, Some vref) -> CheckFSharpAttributesForUnseen g vref.Attribs m allowObsolete | FSProp _ -> failwith "CheckPropInfoAttributes: unreachable" #if !NO_TYPEPROVIDERS | ProvidedProp (_amap, pi, m) -> diff --git a/src/Compiler/Checking/AttributeChecking.fsi b/src/Compiler/Checking/AttributeChecking.fsi index b23681702da..8a9f0742a23 100644 --- a/src/Compiler/Checking/AttributeChecking.fsi +++ b/src/Compiler/Checking/AttributeChecking.fsi @@ -68,7 +68,7 @@ val CheckFSharpAttributesForHidden: g: TcGlobals -> attribs: Attrib list -> bool val CheckFSharpAttributesForObsolete: g: TcGlobals -> attribs: Attrib list -> bool -val CheckFSharpAttributesForUnseen: g: TcGlobals -> attribs: Attrib list -> _m: 'a -> bool +val CheckFSharpAttributesForUnseen: g: TcGlobals -> attribs: Attrib list -> _m: 'a -> allowObsolete: bool -> bool val CheckPropInfoAttributes: pinfo: PropInfo -> m: range -> OperationResult @@ -77,9 +77,9 @@ val CheckILFieldAttributes: g: TcGlobals -> finfo: ILFieldInfo -> m: range -> un val CheckMethInfoAttributes: g: TcGlobals -> m: range -> tyargsOpt: 'a option -> minfo: MethInfo -> OperationResult -val MethInfoIsUnseen: g: TcGlobals -> m: range -> ty: TType -> minfo: MethInfo -> bool +val MethInfoIsUnseen: g: TcGlobals -> m: range -> ty: TType -> minfo: MethInfo -> allowObsolete: bool -> bool -val PropInfoIsUnseen: m: 'a -> pinfo: PropInfo -> bool +val PropInfoIsUnseen: m: 'a -> allowObsolete: bool -> pinfo: PropInfo -> bool val CheckEntityAttributes: g: TcGlobals -> tcref: TyconRef -> m: range -> OperationResult diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 025ccb3c022..2cd07581142 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -4275,28 +4275,27 @@ let IsTyconUnseenObsoleteSpec ad g amap m (x: TyconRef) allowObsolete = (if x.IsILTycon then CheckILAttributesForUnseen g x.ILTyconRawMetadata.CustomAttrs m else - CheckFSharpAttributesForUnseen g x.Attribs m)) + CheckFSharpAttributesForUnseen g x.Attribs m allowObsolete)) -let IsTyconUnseen ad g amap m (x: TyconRef) = IsTyconUnseenObsoleteSpec ad g amap m x false +let IsTyconUnseen ad g amap m allowObsolete (x: TyconRef) = IsTyconUnseenObsoleteSpec ad g amap m x allowObsolete -let IsValUnseen ad g m (v: ValRef) = +let IsValUnseen ad g m allowObsolete (v: ValRef) = v.IsCompilerGenerated || v.Deref.IsClassConstructor || not (IsValAccessible ad v) || - CheckFSharpAttributesForUnseen g v.Attribs m + not allowObsolete && CheckFSharpAttributesForUnseen g v.Attribs m allowObsolete -let IsUnionCaseUnseen ad g amap m (ucref: UnionCaseRef) = +let IsUnionCaseUnseen ad g amap m allowObsolete (ucref: UnionCaseRef) = not (IsUnionCaseAccessible amap m ad ucref) || - IsTyconUnseen ad g amap m ucref.TyconRef || - CheckFSharpAttributesForUnseen g ucref.Attribs m + not allowObsolete && (IsTyconUnseen ad g amap m allowObsolete ucref.TyconRef || CheckFSharpAttributesForUnseen g ucref.Attribs m allowObsolete) -let ItemIsUnseen ad g amap m item = +let ItemIsUnseen ad g amap m allowObsolete item = match item with | Item.Value x -> let isUnseenNameOfOperator = valRefEq g g.nameof_vref x && not (g.langVersion.SupportsFeature LanguageFeature.NameOf) - isUnseenNameOfOperator || IsValUnseen ad g m x - | Item.UnionCase(x, _) -> IsUnionCaseUnseen ad g amap m x.UnionCaseRef - | Item.ExnCase x -> IsTyconUnseen ad g amap m x + isUnseenNameOfOperator || IsValUnseen ad g m allowObsolete x + | Item.UnionCase(x, _) -> IsUnionCaseUnseen ad g amap m allowObsolete x.UnionCaseRef + | Item.ExnCase x -> IsTyconUnseen ad g amap m allowObsolete x | _ -> false let ItemOfTyconRef ncenv m (x: TyconRef) = @@ -4347,7 +4346,7 @@ type ResolveCompletionTargets = | SettablePropertiesAndFields -> false /// Resolve a (possibly incomplete) long identifier to a set of possible resolutions, qualified by type. -let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: ResolveCompletionTargets) m ad statics ty = +let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: ResolveCompletionTargets) m ad statics ty (allowObsolete: bool) = protectAssemblyExploration [] <| fun () -> let g = ncenv.g let amap = ncenv.amap @@ -4361,7 +4360,7 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso match tryAppTy g ty with | ValueSome (tc, tinst) -> tc.UnionCasesAsRefList - |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m >> not) + |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m allowObsolete >> not) |> List.map (fun ucref -> Item.UnionCase(UnionCaseInfo(tinst, ucref), false)) | _ -> [] else [] @@ -4421,8 +4420,10 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso else [] let pinfos = + if allowObsolete then pinfosIncludingUnseen else + pinfosIncludingUnseen - |> List.filter (fun x -> not (PropInfoIsUnseen m x)) + |> List.filter (fun x -> not (PropInfoIsUnseen m allowObsolete x)) let minfoFilter (suppressedMethNames: Zset<_>) (minfo: MethInfo) = let isApplicableMeth = @@ -4459,7 +4460,7 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso not isUnseenDueToBasicObjRules && not minfo.IsInstance = statics && IsMethInfoAccessible amap m ad minfo && - not (MethInfoIsUnseen g m ty minfo) && + not (MethInfoIsUnseen g m ty minfo allowObsolete) && not minfo.IsConstructor && not minfo.IsClassConstructor && (minfo.LogicalName <> ".cctor") && @@ -4572,9 +4573,9 @@ let FullTypeOfPropInfo g amap m (pinfo: PropInfo) = else ty ty -let rec ResolvePartialLongIdentInType (ncenv: NameResolver) nenv isApplicableMeth m ad statics plid ty = +let rec ResolvePartialLongIdentInType (ncenv: NameResolver) nenv isApplicableMeth m ad statics plid ty (allowObsolete: bool) = match plid with - | [] -> ResolveCompletionsInType ncenv nenv isApplicableMeth m ad statics ty + | [] -> ResolveCompletionsInType ncenv nenv isApplicableMeth m ad statics ty allowObsolete | id :: rest -> [ let g = ncenv.g @@ -4583,33 +4584,33 @@ let rec ResolvePartialLongIdentInType (ncenv: NameResolver) nenv isApplicableMet // e.g. .. for fref in ncenv.InfoReader.GetRecordOrClassFieldsOfType(None, ad, m, ty) do if fref.LogicalName = id && IsRecdFieldAccessible ncenv.amap m ad fref.RecdFieldRef && fref.RecdField.IsStatic = statics then - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest fref.FieldType + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest fref.FieldType allowObsolete for pinfo in AllPropInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv (Some id) ad IgnoreOverrides m ty do if pinfo.IsStatic = statics && IsPropInfoAccessible g amap m ad pinfo then let pinfoTy = FullTypeOfPropInfo g amap m pinfo - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest pinfoTy + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest pinfoTy allowObsolete if not statics then match TryFindAnonRecdFieldOfType g ty id with | Some (Item.AnonRecdField(_, tys, i, _)) -> - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest tys[i] + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest tys[i] allowObsolete | _ -> () // e.g. .. for einfo in ncenv.InfoReader.GetEventInfosOfType(Some id, ad, m, ty) do let einfoTy = PropTypeOfEventInfo ncenv.InfoReader m ad einfo - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest einfoTy + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest einfoTy allowObsolete // nested types for nestedTy in GetNestedTypesOfType (ad, ncenv, Some id, TypeNameResolutionStaticArgsInfo.Indefinite, false, m) ty do - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad statics rest nestedTy + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad statics rest nestedTy allowObsolete // e.g. .. for finfo in ncenv.InfoReader.GetILFieldInfosOfType(Some id, ad, m, ty) do if not finfo.IsSpecialName && finfo.IsStatic = statics && IsILFieldInfoAccessible g amap m ad finfo then let finfoTy = finfo.FieldType(amap, m) - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest finfoTy + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest finfoTy allowObsolete ] let InfosForTyconConstructors (ncenv: NameResolver) m ad (tcref: TyconRef) = @@ -4627,7 +4628,7 @@ let InfosForTyconConstructors (ncenv: NameResolver) m ad (tcref: TyconRef) = ctorInfos |> List.filter (fun minfo -> IsMethInfoAccessible amap m ad minfo && - not (MethInfoIsUnseen g m ty minfo)) + not (MethInfoIsUnseen g m ty minfo false)) match ctors with | [] -> None | _ -> Some(Item.MakeCtorGroup(nm, ctors)) @@ -4642,7 +4643,7 @@ let inline notFakeContainerModule (tyconNames: HashSet<_>) nm = not (tyconNames.Contains nm) /// Check is a namespace or module contains something accessible -let rec private EntityRefContainsSomethingAccessible (ncenv: NameResolver) m ad (modref: ModuleOrNamespaceRef) = +let rec private EntityRefContainsSomethingAccessible (ncenv: NameResolver) m ad allowObsolete (modref: ModuleOrNamespaceRef) = let g = ncenv.g let mty = modref.ModuleOrNamespaceType @@ -4661,22 +4662,22 @@ let rec private EntityRefContainsSomethingAccessible (ncenv: NameResolver) m ad (fun () -> let vref = mkNestedValRef modref v not vref.IsCompilerGenerated && - not (IsValUnseen ad g m vref) && + not (IsValUnseen ad g m allowObsolete vref) && (vref.IsExtensionMember || not vref.IsMember)))) || // Search the types in the namespace/module for an accessible tycon (mty.AllEntities |> QueueList.exists (fun tc -> not tc.IsModuleOrNamespace && - not (IsTyconUnseen ad g ncenv.amap m (modref.NestedTyconRef tc)))) || + not (IsTyconUnseen ad g ncenv.amap m allowObsolete (modref.NestedTyconRef tc)))) || // Search the sub-modules of the namespace/module for something accessible (mty.ModulesAndNamespacesByDemangledName |> NameMap.exists (fun _ submod -> let submodref = modref.NestedTyconRef submod - EntityRefContainsSomethingAccessible ncenv m ad submodref)) + EntityRefContainsSomethingAccessible ncenv m ad allowObsolete submodref)) -let GetVisibleNamespacesAndModulesAtPoint (ncenv: NameResolver) (nenv: NameResolutionEnv) fullyQualified m ad = +let GetVisibleNamespacesAndModulesAtPoint (ncenv: NameResolver) (nenv: NameResolutionEnv) fullyQualified m ad allowObsolete = protectAssemblyExploration [] (fun () -> let items = nenv.ModulesAndNamespaces fullyQualified @@ -4696,10 +4697,10 @@ let GetVisibleNamespacesAndModulesAtPoint (ncenv: NameResolver) (nenv: NameResol |> List.filter (fun x -> let demangledName = x.DemangledModuleOrNamespaceName IsInterestingModuleName demangledName && notFakeContainerModule ilTyconNames demangledName - && EntityRefContainsSomethingAccessible ncenv m ad x - && not (IsTyconUnseen ad ncenv.g ncenv.amap m x))) + && EntityRefContainsSomethingAccessible ncenv m ad allowObsolete x + && not (IsTyconUnseen ad ncenv.g ncenv.amap m allowObsolete x))) -let GetAccessibleSubModules g (ncenv: NameResolver) (modref: ModuleOrNamespaceRef) m ad = +let GetAccessibleSubModules g (ncenv: NameResolver) (modref: ModuleOrNamespaceRef) m ad (allowObsolete: bool) = let moduleOrNamespaces = modref.ModuleOrNamespaceType.ModulesAndNamespacesByDemangledName |> NameMap.range @@ -4720,8 +4721,8 @@ let GetAccessibleSubModules g (ncenv: NameResolver) (modref: ModuleOrNamespaceRe notFakeContainerModule ilTyconNames demangledName && IsInterestingModuleName demangledName) |> List.map modref.NestedTyconRef |> List.filter (fun tyref -> - not (IsTyconUnseen ad g ncenv.amap m tyref) && - EntityRefContainsSomethingAccessible ncenv m ad tyref) + not (IsTyconUnseen ad g ncenv.amap m allowObsolete tyref) && + EntityRefContainsSomethingAccessible ncenv m ad allowObsolete tyref) |> List.map ItemForModuleOrNamespaceRef let rec ResolvePartialLongIdentInModuleOrNamespace (ncenv: NameResolver) nenv isApplicableMeth m ad (modref: ModuleOrNamespaceRef) plid allowObsolete = @@ -4733,35 +4734,35 @@ let rec ResolvePartialLongIdentInModuleOrNamespace (ncenv: NameResolver) nenv is let tycons = mty.TypeDefinitions |> List.filter (fun tcref -> not (tcref.LogicalName.Contains ",") && - not (IsTyconUnseen ad g ncenv.amap m (modref.NestedTyconRef tcref))) + not (IsTyconUnseen ad g ncenv.amap m allowObsolete (modref.NestedTyconRef tcref))) // Collect up the accessible values in the module, excluding the members (mty.AllValsAndMembers |> Seq.toList |> List.choose (TryMkValRefInModRef modref) // if the assembly load set is incomplete and we get a None value here, then ignore the value - |> List.filter (fun vref -> not vref.IsMember && not (IsValUnseen ad g m vref)) + |> List.filter (fun vref -> not vref.IsMember && not (IsValUnseen ad g m allowObsolete vref)) |> List.map Item.Value) // Collect up the accessible discriminated union cases in the module @ (UnionCaseRefsInModuleOrNamespace modref - |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m >> not) + |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m allowObsolete >> not) |> List.filter (fun ucref -> not (HasFSharpAttribute g g.attrib_RequireQualifiedAccessAttribute ucref.TyconRef.Attribs)) |> List.map (fun x -> Item.UnionCase(GeneralizeUnionCaseRef x, false))) // Collect up the accessible active patterns in the module @ (ActivePatternElemsOfModuleOrNamespace g modref |> NameMap.range - |> List.filter (fun apref -> apref.ActivePatternVal |> IsValUnseen ad g m |> not) + |> List.filter (fun apref -> apref.ActivePatternVal |> IsValUnseen ad g m allowObsolete |> not) |> List.map Item.ActivePatternCase) // Collect up the accessible F# exception declarations in the module @ (mty.ExceptionDefinitionsByDemangledName |> NameMap.range |> List.map modref.NestedTyconRef - |> List.filter (IsTyconUnseen ad g ncenv.amap m >> not) + |> List.filter (IsTyconUnseen ad g ncenv.amap m allowObsolete >> not) |> List.map Item.ExnCase) - @ GetAccessibleSubModules g ncenv modref m ad + @ GetAccessibleSubModules g ncenv modref m ad allowObsolete // Get all the types and .NET constructor groups accessible from here @ (tycons @@ -4786,7 +4787,7 @@ let rec ResolvePartialLongIdentInModuleOrNamespace (ncenv: NameResolver) nenv is let tcref = modref.NestedTyconRef tycon if not (IsTyconUnseenObsoleteSpec ad g ncenv.amap m tcref allowObsolete) then let ty = generalizedTyconRef g tcref - ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad true rest ty + ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad true rest ty allowObsolete else [])) @@ -4822,7 +4823,7 @@ let TryToResolveLongIdentAsType (ncenv: NameResolver) (nenv: NameResolutionEnv) /// allowObsolete - specifies whether we should return obsolete types & modules /// as (no other obsolete items are returned) -let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionEnv) isApplicableMeth fullyQualified m ad plid allowObsolete: Item list = +let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionEnv) isApplicableMeth fullyQualified m ad plid (allowObsolete: bool): Item list = let g = ncenv.g match plid with @@ -4843,7 +4844,7 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE | Item.UnqualifiedType _ -> false | Item.Value v -> not v.IsMember | _ -> true) - |> Seq.filter (ItemIsUnseen ad g ncenv.amap m >> not) + |> Seq.filter (ItemIsUnseen ad g ncenv.amap m allowObsolete >> not) |> Seq.toList let activePatternItems = @@ -4855,21 +4856,21 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE |> List.filter (function Item.ActivePatternCase _v -> true | _ -> false) let moduleAndNamespaceItems = - GetVisibleNamespacesAndModulesAtPoint ncenv nenv fullyQualified m ad |> List.map ItemForModuleOrNamespaceRef + GetVisibleNamespacesAndModulesAtPoint ncenv nenv fullyQualified m ad allowObsolete |> List.map ItemForModuleOrNamespaceRef let tycons = nenv.TyconsByDemangledNameAndArity(fullyQualified).Values |> Seq.filter (fun tcref -> not (tcref.LogicalName.Contains ",") && not tcref.IsFSharpException && - not (IsTyconUnseen ad g ncenv.amap m tcref)) + not (IsTyconUnseen ad g ncenv.amap m allowObsolete tcref)) |> Seq.map (ItemOfTyconRef ncenv m) |> Seq.toList // Get all the constructors accessible from here let constructors = nenv.TyconsByDemangledNameAndArity(fullyQualified).Values - |> Seq.filter (IsTyconUnseen ad g ncenv.amap m >> not) + |> Seq.filter (IsTyconUnseen ad g ncenv.amap m allowObsolete >> not) |> Seq.choose (InfosForTyconConstructors ncenv m ad) |> Seq.toList @@ -4888,8 +4889,8 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE // Look in the namespaces 'id' let namespaces = PartialResolveLongIdentAsModuleOrNamespaceThen nenv [id] (fun modref -> - let allowObsolete = rest <> [] && allowObsolete - if EntityRefContainsSomethingAccessible ncenv m ad modref then + let allowObsolete = rest <> [] || allowObsolete + if EntityRefContainsSomethingAccessible ncenv m ad allowObsolete modref then ResolvePartialLongIdentInModuleOrNamespace ncenv nenv isApplicableMeth m ad modref rest allowObsolete else []) @@ -4903,7 +4904,7 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE | Item.Value x -> let ty = x.Type let ty = if x.IsCtorThisVal && isRefCellTy g ty then destRefCellTy g ty else ty - (ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest ty), true + (ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad false rest ty allowObsolete), true | _ -> [], false | _ -> [], false) @@ -4913,14 +4914,14 @@ let rec ResolvePartialLongIdentPrim (ncenv: NameResolver) (nenv: NameResolutionE for tcref in LookupTypeNameInEnvNoArity OpenQualified id nenv do let tcref = ResolveNestedTypeThroughAbbreviation ncenv tcref m let ty = FreshenTycon ncenv m tcref - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad true rest ty + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad true rest ty allowObsolete // 'T.Ident: lookup a static something in a type parameter // ^T.Ident: lookup a static something in a type parameter match nenv.eTypars.TryGetValue id with | true, tp -> let ty = mkTyparTy tp - yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad true rest ty + yield! ResolvePartialLongIdentInType ncenv nenv isApplicableMeth m ad true rest ty allowObsolete | _ -> () ] namespaces @ values @ staticSomethingInType @@ -4942,10 +4943,10 @@ let rec ResolvePartialLongIdentInModuleOrNamespaceForRecordFields (ncenv: NameRe |> List.filter (fun tcref -> not (tcref.LogicalName.Contains ",") && tcref.IsRecordTycon && - not (IsTyconUnseen ad g ncenv.amap m (modref.NestedTyconRef tcref))) + not (IsTyconUnseen ad g ncenv.amap m allowObsolete (modref.NestedTyconRef tcref))) - GetAccessibleSubModules g ncenv modref m ad + GetAccessibleSubModules g ncenv modref m ad allowObsolete // Collect all accessible record types @ (tycons |> List.map (modref.NestedTyconRef >> ItemOfTyconRef ncenv m) ) @@ -5009,14 +5010,14 @@ and ResolvePartialLongIdentToClassOrRecdFieldsImpl (ncenv: NameResolver) (nenv: if fieldsOnly then getRecordFieldsInScope nenv else let mods = - GetVisibleNamespacesAndModulesAtPoint ncenv nenv fullyQualified m ad |> List.map ItemForModuleOrNamespaceRef + GetVisibleNamespacesAndModulesAtPoint ncenv nenv fullyQualified m ad allowObsolete |> List.map ItemForModuleOrNamespaceRef let recdTyCons = nenv.TyconsByDemangledNameAndArity(fullyQualified).Values |> Seq.filter (fun tcref -> not (tcref.LogicalName.Contains ",") && tcref.IsRecordTycon && - not (IsTyconUnseen ad g ncenv.amap m tcref)) + not (IsTyconUnseen ad g ncenv.amap m allowObsolete tcref)) |> Seq.map (ItemOfTyconRef ncenv m) |> Seq.toList @@ -5030,7 +5031,7 @@ and ResolvePartialLongIdentToClassOrRecdFieldsImpl (ncenv: NameResolver) (nenv: let modsOrNs = PartialResolveLongIdentAsModuleOrNamespaceThen nenv [id] (fun modref -> let allowObsolete = rest <> [] && allowObsolete - if EntityRefContainsSomethingAccessible ncenv m ad modref then + if EntityRefContainsSomethingAccessible ncenv m ad allowObsolete modref then ResolvePartialLongIdentInModuleOrNamespaceForRecordFields ncenv nenv m ad modref rest allowObsolete else []) @@ -5063,7 +5064,7 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty ( | ValueSome(tc, tinst) -> yield! tc.UnionCasesAsRefList - |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m >> not) + |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m false >> not) |> List.map (fun ucref -> Item.UnionCase(UnionCaseInfo(tinst, ucref), false)) | _ -> () | Item.Event _ -> @@ -5126,7 +5127,7 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty ( let pinfos = pinfosIncludingUnseen - |> List.filter (fun x -> not (PropInfoIsUnseen m x)) + |> List.filter (fun x -> not (PropInfoIsUnseen m false x)) let minfoFilter (suppressedMethNames: Zset<_>) (minfo: MethInfo) = // Only show the Finalize, MemberwiseClose etc. methods on System.Object for values whose static type really is @@ -5157,7 +5158,7 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty ( not isUnseenDueToBasicObjRules && not minfo.IsInstance = statics && IsMethInfoAccessible amap m ad minfo && - not (MethInfoIsUnseen g m ty minfo) && + not (MethInfoIsUnseen g m ty minfo false) && not minfo.IsConstructor && not minfo.IsClassConstructor && (minfo.LogicalName <> ".cctor") && @@ -5300,14 +5301,14 @@ let rec ResolvePartialLongIdentInModuleOrNamespaceForItem (ncenv: NameResolver) mty.AllValsAndMembers |> Seq.toList |> List.choose (TryMkValRefInModRef modref) // if the assembly load set is incomplete and we get a None value here, then ignore the value - |> List.filter (fun vref -> not vref.IsMember && not (IsValUnseen ad g m vref)) + |> List.filter (fun vref -> not vref.IsMember && not (IsValUnseen ad g m false vref)) |> List.map Item.Value | Item.UnionCase _ -> // Collect up the accessible discriminated union cases in the module yield! UnionCaseRefsInModuleOrNamespace modref - |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m >> not) + |> List.filter (IsUnionCaseUnseen ad g ncenv.amap m false >> not) |> List.filter (fun ucref -> not (HasFSharpAttribute g g.attrib_RequireQualifiedAccessAttribute ucref.TyconRef.Attribs)) |> List.map (fun x -> Item.UnionCase(GeneralizeUnionCaseRef x, false)) @@ -5316,7 +5317,7 @@ let rec ResolvePartialLongIdentInModuleOrNamespaceForItem (ncenv: NameResolver) yield! ActivePatternElemsOfModuleOrNamespace g modref |> NameMap.range - |> List.filter (fun apref -> apref.ActivePatternVal |> IsValUnseen ad g m |> not) + |> List.filter (fun apref -> apref.ActivePatternVal |> IsValUnseen ad g m false |> not) |> List.map Item.ActivePatternCase | Item.ExnCase _ -> @@ -5325,19 +5326,19 @@ let rec ResolvePartialLongIdentInModuleOrNamespaceForItem (ncenv: NameResolver) mty.ExceptionDefinitionsByDemangledName |> NameMap.range |> List.map modref.NestedTyconRef - |> List.filter (IsTyconUnseen ad g ncenv.amap m >> not) + |> List.filter (IsTyconUnseen ad g ncenv.amap m false >> not) |> List.map Item.ExnCase | _ -> // Collect up the accessible sub-modules. We must yield them even though `item` is not a module or namespace, // otherwise we would not resolve long idents which have modules and namespaces in the middle (i.e. all long idents) - yield! GetAccessibleSubModules g ncenv modref m ad + yield! GetAccessibleSubModules g ncenv modref m ad false let tycons = mty.TypeDefinitions |> List.filter (fun tcref -> not (tcref.LogicalName.Contains ",") && - not (IsTyconUnseen ad g ncenv.amap m (modref.NestedTyconRef tcref))) + not (IsTyconUnseen ad g ncenv.amap m false (modref.NestedTyconRef tcref))) // Get all the types and .NET constructor groups accessible from here let nestedTycons = tycons |> List.map modref.NestedTyconRef @@ -5399,19 +5400,19 @@ let rec GetCompletionForItem (ncenv: NameResolver) (nenv: NameResolutionEnv) m a for uitem in nenv.eUnqualifiedItems.Values do match uitem with | Item.UnqualifiedType _ -> () - | _ when not (ItemIsUnseen ad g ncenv.amap m uitem) -> + | _ when not (ItemIsUnseen ad g ncenv.amap m false uitem) -> yield uitem | _ -> () match item with | Item.ModuleOrNamespaces _ -> - yield! GetVisibleNamespacesAndModulesAtPoint ncenv nenv OpenQualified m ad |> List.map ItemForModuleOrNamespaceRef + yield! GetVisibleNamespacesAndModulesAtPoint ncenv nenv OpenQualified m ad false |> List.map ItemForModuleOrNamespaceRef | Item.Types _ -> for tcref in nenv.TyconsByDemangledNameAndArity(OpenQualified).Values do if not tcref.IsFSharpException && not (tcref.LogicalName.Contains ",") - && not (IsTyconUnseen ad g ncenv.amap m tcref) + && not (IsTyconUnseen ad g ncenv.amap m false tcref) then yield ItemOfTyconRef ncenv m tcref | Item.ActivePatternCase _ -> @@ -5425,7 +5426,7 @@ let rec GetCompletionForItem (ncenv: NameResolver) (nenv: NameResolutionEnv) m a | Item.CtorGroup _ | Item.UnqualifiedType _ -> for tcref in nenv.TyconsByDemangledNameAndArity(OpenQualified).Values do - if not (IsTyconUnseen ad g ncenv.amap m tcref) then + if not (IsTyconUnseen ad g ncenv.amap m false tcref) then match InfosForTyconConstructors ncenv m ad tcref with | Some info -> yield info | _ -> () @@ -5436,7 +5437,7 @@ let rec GetCompletionForItem (ncenv: NameResolver) (nenv: NameResolutionEnv) m a // Look in the namespaces 'id' yield! PartialResolveLongIdentAsModuleOrNamespaceThenLazy nenv [id] (fun modref -> - if EntityRefContainsSomethingAccessible ncenv m ad modref then + if EntityRefContainsSomethingAccessible ncenv m ad false modref then ResolvePartialLongIdentInModuleOrNamespaceForItem ncenv nenv m ad modref rest item else Seq.empty) diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 48c164433c2..c4e08188c4c 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -913,10 +913,17 @@ val ResolveCompletionsInType: AccessorDomain -> bool -> TType -> + allowObsolete: bool -> Item list val GetVisibleNamespacesAndModulesAtPoint: - NameResolver -> NameResolutionEnv -> FullyQualifiedFlag -> range -> AccessorDomain -> ModuleOrNamespaceRef list + NameResolver -> + NameResolutionEnv -> + FullyQualifiedFlag -> + range -> + AccessorDomain -> + allowObsolete: bool -> + ModuleOrNamespaceRef list val IsItemResolvable: NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> string list -> Item -> bool diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 0609fd8c6ce..afc58ee7a25 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -333,6 +333,22 @@ type ExprTypingsResult = type Names = string list +type FSharpCodeCompletionOptions = + { + SuggestPatternNames: bool + SuggestObsoleteSymbols: bool + SuggestGeneratedOverrides: bool + SuggestOverrideBodies: bool + } + + static member Default = + { + SuggestPatternNames = true + SuggestObsoleteSymbols = false + SuggestGeneratedOverrides = true + SuggestOverrideBodies = true + } + /// A TypeCheckInfo represents everything we get back from the typecheck of a file. /// It acts like an in-memory database about the file. /// It is effectively immutable and not updated: when we re-typecheck we just drop the previous @@ -481,7 +497,7 @@ type internal TypeCheckInfo /// Looks at the exact name resolutions that occurred during type checking /// If 'membersByResidue' is specified, we look for members of the item obtained /// from the name resolution and filter them by the specified residue (?) - let GetPreciseItemsFromNameResolution (line, colAtEndOfNames, membersByResidue, filterCtors, resolveOverloads) = + let GetPreciseItemsFromNameResolution (line, colAtEndOfNames, membersByResidue, filterCtors, resolveOverloads, allowObsolete) = let endOfNamesPos = mkPos line colAtEndOfNames // Logic below expects the list to be in reverse order of resolution @@ -502,7 +518,7 @@ type internal TypeCheckInfo let targets = ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m) - let items = ResolveCompletionsInType ncenv nenv targets m ad true ty + let items = ResolveCompletionsInType ncenv nenv targets m ad true ty allowObsolete let items = List.map ItemWithNoInst items ReturnItemsOfType items g denv m filterCtors @@ -511,7 +527,9 @@ type internal TypeCheckInfo let targets = ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m) - let items = ResolveCompletionsInType ncenv nenv targets m ad true (mkTyparTy tp) + let items = + ResolveCompletionsInType ncenv nenv targets m ad true (mkTyparTy tp) allowObsolete + let items = List.map ItemWithNoInst items ReturnItemsOfType items g denv m filterCtors @@ -547,7 +565,7 @@ type internal TypeCheckInfo let targets = ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m) - let items = ResolveCompletionsInType ncenv nenv targets m ad false ty + let items = ResolveCompletionsInType ncenv nenv targets m ad false ty allowObsolete let items = List.map ItemWithNoInst items ReturnItemsOfType items g denv m filterCtors @@ -660,7 +678,7 @@ type internal TypeCheckInfo | None -> None) | _ -> []) - let GetNamedParametersAndSettableFields endOfExprPos = + let GetNamedParametersAndSettableFields endOfExprPos allowObsolete = let cnrs = GetCapturedNameResolutions endOfExprPos ResolveOverloads.No |> ResizeArray.toList @@ -678,6 +696,7 @@ type internal TypeCheckInfo ad false ctor.ApparentEnclosingType + allowObsolete let parameters = CollectParameters ctors amap m let items = props @ parameters @@ -687,7 +706,16 @@ type internal TypeCheckInfo methods |> List.collect (fun meth -> let retTy = meth.GetFSharpReturnType(amap, m, meth.FormalMethodInst) - ResolveCompletionsInType ncenv nenv ResolveCompletionTargets.SettablePropertiesAndFields m ad false retTy) + + ResolveCompletionsInType + ncenv + nenv + ResolveCompletionTargets.SettablePropertiesAndFields + m + ad + false + retTy + allowObsolete) let parameters = CollectParameters methods amap m let items = props @ parameters @@ -778,7 +806,7 @@ type internal TypeCheckInfo /// Looks at the exact expression types at the position to the left of the /// residue then the source when it was typechecked. - let GetPreciseCompletionListFromExprTypings (parseResults: FSharpParseFileResults, endOfExprPos, filterCtors) = + let GetPreciseCompletionListFromExprTypings (parseResults: FSharpParseFileResults, endOfExprPos, filterCtors, allowObsolete: bool) = let thereWereSomeQuals, quals = GetExprTypingForPosition(endOfExprPos) @@ -818,7 +846,7 @@ type internal TypeCheckInfo let targets = ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m) - let items = ResolveCompletionsInType ncenv nenv targets m ad false ty + let items = ResolveCompletionsInType ncenv nenv targets m ad false ty allowObsolete let items = items |> List.map ItemWithNoInst let items = items |> RemoveDuplicateItems g let items = items |> RemoveExplicitlySuppressed g @@ -847,11 +875,11 @@ type internal TypeCheckInfo GetEnvironmentLookupResolutions(nenv, ad, m, plid, filterCtors, showObsolete) /// Find record fields in the best naming environment. - let GetClassOrRecordFieldsEnvironmentLookupResolutions (cursorPos, plid, fieldsOnly) = + let GetClassOrRecordFieldsEnvironmentLookupResolutions (cursorPos, plid, fieldsOnly, allowObsolete) = let (nenv, ad), m = GetBestEnvForPos cursorPos let items = - ResolvePartialLongIdentToClassOrRecdFields ncenv nenv m ad plid false fieldsOnly + ResolvePartialLongIdentToClassOrRecdFields ncenv nenv m ad plid allowObsolete fieldsOnly let items = items |> List.map ItemWithNoInst let items = items |> RemoveDuplicateItems g @@ -1063,7 +1091,7 @@ type internal TypeCheckInfo |> Option.defaultValue completions /// Gets all methods that a type can override, but has not yet done so. - let GetOverridableMethods pos ctx (typeNameRange: range) newlineIndentCount hasThis isStatic genBodyForOverriddenMeth = + let GetOverridableMethods pos ctx (typeNameRange: range) newlineIndentCount hasThis isStatic (options: FSharpCodeCompletionOptions) = let checkImplementedSlotDeclareType ty slots = slots |> Option.map (List.exists (fun (TSlotSig(declaringType = ty2)) -> typeEquiv g ty ty2)) @@ -1113,7 +1141,7 @@ type internal TypeCheckInfo /// Check if the method is abstract, return "raise (NotImplementedException())" if it is abstract, otherwise return the given body let checkMethAbstractAndGetImplementBody (meth: MethInfo) implementBody = - if not genBodyForOverriddenMeth then + if not options.SuggestOverrideBodies then String.Empty elif meth.IsAbstract then if nenv.DisplayEnv.openTopPathsSorted.Force() |> List.contains [ "System" ] then @@ -1345,7 +1373,14 @@ type internal TypeCheckInfo let getTyFromTypeNamePos (endPos: pos) = let nameResItems = - GetPreciseItemsFromNameResolution(endPos.Line, endPos.Column, None, ResolveTypeNamesToTypeRefs, ResolveOverloads.Yes) + GetPreciseItemsFromNameResolution( + endPos.Line, + endPos.Column, + None, + ResolveTypeNamesToTypeRefs, + ResolveOverloads.Yes, + options.SuggestObsoleteSymbols + ) match nameResItems with | NameResResult.Members(ls, _, _) -> @@ -1419,7 +1454,7 @@ type internal TypeCheckInfo |> Some | _ -> None) - let GetCompletionsForUnionCaseField pos indexOrName caseIdRange isTheOnlyField declaredItems = + let GetCompletionsForUnionCaseField pos indexOrName caseIdRange isTheOnlyField suggestPatternNames declaredItems = let declaredItems = declaredItems |> Option.bind (FilterRelevantItemsBy getItem2 None IsPatternCandidate) @@ -1433,19 +1468,27 @@ type internal TypeCheckInfo |> List.mapi (fun index _ -> Item.UnionCaseField(uci, index) |> ItemWithNoInst |> DefaultCompletionItem) | _ -> [] - sResolutions.CapturedNameResolutions - |> ResizeArray.tryPick (fun r -> - match r.Item with - | Item.UnionCase(uci, _) when equals r.Range caseIdRange -> - let list = - declaredItems - |> Option.map p13 - |> Option.defaultValue [] - |> List.append (fields indexOrName isTheOnlyField uci) + if not suggestPatternNames then + declaredItems + else - Some(SuggestNameForUnionCaseFieldPattern g caseIdRange.End pos uci indexOrName isTheOnlyField list, r.DisplayEnv, r.Range) - | _ -> None) - |> Option.orElse declaredItems + sResolutions.CapturedNameResolutions + |> ResizeArray.tryPick (fun r -> + match r.Item with + | Item.UnionCase(uci, _) when equals r.Range caseIdRange -> + let list = + declaredItems + |> Option.map p13 + |> Option.defaultValue [] + |> List.append (fields indexOrName isTheOnlyField uci) + + Some( + SuggestNameForUnionCaseFieldPattern g caseIdRange.End pos uci indexOrName isTheOnlyField list, + r.DisplayEnv, + r.Range + ) + | _ -> None) + |> Option.orElse declaredItems let GetCompletionsForRecordField pos referencedFields declaredItems = declaredItems @@ -1499,7 +1542,8 @@ type internal TypeCheckInfo filterCtors, resolveOverloads, isInRangeOperator, - allSymbols: unit -> AssemblySymbol list + allSymbols: unit -> AssemblySymbol list, + options: FSharpCodeCompletionOptions ) = // Are the last two chars (except whitespaces) = ".." @@ -1517,7 +1561,15 @@ type internal TypeCheckInfo // This is based on position (i.e. colAtEndOfNamesAndResidue). This is not used if a residueOpt is given. let nameResItems = match residueOpt with - | None -> GetPreciseItemsFromNameResolution(line, colAtEndOfNamesAndResidue, None, filterCtors, resolveOverloads) + | None -> + GetPreciseItemsFromNameResolution( + line, + colAtEndOfNamesAndResidue, + None, + filterCtors, + resolveOverloads, + options.SuggestObsoleteSymbols + ) | Some residue -> // Deals with cases when we have spaces between dot and\or identifier, like A . $ // if this is our case - then we need to locate end position of the name skipping whitespaces @@ -1531,7 +1583,15 @@ type internal TypeCheckInfo match FindFirstNonWhitespacePosition lineStr (p - 1) with | Some colAtEndOfNames -> let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based - GetPreciseItemsFromNameResolution(line, colAtEndOfNames, Some(residue), filterCtors, resolveOverloads) + + GetPreciseItemsFromNameResolution( + line, + colAtEndOfNames, + Some(residue), + filterCtors, + resolveOverloads, + options.SuggestObsoleteSymbols + ) | None -> NameResResult.Empty | _ -> NameResResult.Empty @@ -1598,7 +1658,9 @@ type internal TypeCheckInfo ) match leftOfDot with - | Some(pos, _) -> GetPreciseCompletionListFromExprTypings(parseResults, pos, filterCtors), true + | Some(pos, _) -> + GetPreciseCompletionListFromExprTypings(parseResults, pos, filterCtors, options.SuggestObsoleteSymbols), + true | None -> // Can get here in a case like: if "f xxx yyy" is legal, and we do "f xxx y" // We have no interest in expression typings, those are only useful for dot-completion. We want to fallback @@ -1630,7 +1692,8 @@ type internal TypeCheckInfo | _ -> // Use an environment lookup as the last resort let envItems, denv, m = - GetEnvironmentLookupResolutions(nenv, ad, m, plid, filterCtors, residueOpt.IsSome) + let allowObsolete = options.SuggestObsoleteSymbols + GetEnvironmentLookupResolutions(nenv, ad, m, plid, filterCtors, allowObsolete) let envResult = match nameResItems, (envItems, denv, m), qualItems with @@ -1692,7 +1755,7 @@ type internal TypeCheckInfo items |> List.map DefaultCompletionItem, denv, m /// Find record fields in the best naming environment. - let GetEnvironmentLookupResolutionsIncludingRecordFieldsAtPosition cursorPos plid envItems = + let GetEnvironmentLookupResolutionsIncludingRecordFieldsAtPosition cursorPos plid envItems (options: FSharpCodeCompletionOptions) = // An empty record expression may be completed into something like these: // { XXX = ... } // { xxx with XXX ... } @@ -1700,7 +1763,7 @@ type internal TypeCheckInfo let (nenv, _), m = GetBestEnvForPos cursorPos let fieldItems, _, _ = - GetClassOrRecordFieldsEnvironmentLookupResolutions(cursorPos, plid, true) + GetClassOrRecordFieldsEnvironmentLookupResolutions(cursorPos, plid, true, options.SuggestObsoleteSymbols) let fieldCompletionItems, _, _ as fieldsResult = (fieldItems, nenv.DisplayEnv, m) |> toCompletionItems @@ -1723,7 +1786,7 @@ type internal TypeCheckInfo resolveOverloads, completionContextAtPos: (pos * CompletionContext option) option, getAllSymbols: unit -> AssemblySymbol list, - genBodyForOverriddenMeth + options: FSharpCodeCompletionOptions ) : (CompletionItem list * DisplayEnv * CompletionContext option * range) option = let loc = @@ -1746,7 +1809,8 @@ type internal TypeCheckInfo filterCtors, resolveOverloads, false, - getAllSymbols + getAllSymbols, + options ) let pos = mkPos line colAtEndOfNamesAndResidue @@ -1807,14 +1871,15 @@ type internal TypeCheckInfo filterCtors, resolveOverloads, false, - fun () -> [] + (fun () -> []), + options ) - GetEnvironmentLookupResolutionsIncludingRecordFieldsAtPosition cursorPos plid envItems + GetEnvironmentLookupResolutionsIncludingRecordFieldsAtPosition cursorPos plid envItems options else // { x. } can be either record construction or computation expression. Try to get all visible record fields first match - GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, plid, false) + GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, plid, false, options.SuggestObsoleteSymbols) |> toCompletionItems with | [], _, _ -> @@ -1831,7 +1896,8 @@ type internal TypeCheckInfo filterCtors, resolveOverloads, false, - fun () -> [] + (fun () -> []), + options ) | result -> Some(result) @@ -1852,22 +1918,23 @@ type internal TypeCheckInfo filterCtors, resolveOverloads, false, - fun () -> [] + (fun () -> []), + options ) - GetEnvironmentLookupResolutionsIncludingRecordFieldsAtPosition cursorPos [] envItems + GetEnvironmentLookupResolutionsIncludingRecordFieldsAtPosition cursorPos [] envItems options // Completion at ' { XXX = ... with ... } " | Some(CompletionContext.RecordField(RecordContext.CopyOnUpdate(identRange, (plid, _)))) -> match GetRecdFieldsForCopyAndUpdateExpr(identRange, plid) with | None -> - Some(GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, plid, false)) + Some(GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, plid, false, options.SuggestObsoleteSymbols)) |> Option.map toCompletionItems | Some(items, denv, m) -> Some(List.map ItemWithNoInst items, denv, m) |> Option.map toCompletionItems // Completion at ' { XXX = ... with ... } " | Some(CompletionContext.RecordField(RecordContext.Constructor(typeName))) -> - GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, [ typeName ], false) + GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, [ typeName ], false, options.SuggestObsoleteSymbols) |> toCompletionItems |> Some @@ -1876,7 +1943,8 @@ type internal TypeCheckInfo // Completion at ' SomeMethod( ... ) ' or ' [] ' with named arguments | Some(CompletionContext.ParameterList(endPos, fields)) -> - let results = GetNamedParametersAndSettableFields endPos + let results = + GetNamedParametersAndSettableFields endPos options.SuggestObsoleteSymbols let declaredItems = getDeclaredItemsNotInRangeOpWithAllSymbols () @@ -1948,10 +2016,10 @@ type internal TypeCheckInfo completions, nenv.DisplayEnv, m) | PatternContext.PositionalUnionCaseField(fieldIndex, isTheOnlyField, caseIdRange) -> getDeclaredItemsNotInRangeOpWithAllSymbols () - |> GetCompletionsForUnionCaseField pos (Choice1Of2 fieldIndex) caseIdRange isTheOnlyField + |> GetCompletionsForUnionCaseField pos (Choice1Of2 fieldIndex) caseIdRange isTheOnlyField options.SuggestPatternNames | PatternContext.NamedUnionCaseField(fieldName, caseIdRange) -> getDeclaredItemsNotInRangeOpWithAllSymbols () - |> GetCompletionsForUnionCaseField pos (Choice2Of2 fieldName) caseIdRange false + |> GetCompletionsForUnionCaseField pos (Choice2Of2 fieldName) caseIdRange false options.SuggestPatternNames | PatternContext.RecordFieldIdentifier referencedFields -> getDeclaredItemsNotInRangeOpWithAllSymbols () |> GetCompletionsForRecordField pos referencedFields @@ -1964,17 +2032,10 @@ type internal TypeCheckInfo spacesBeforeOverrideKeyword, hasThis, isStatic, - spacesBeforeEnclosingDefinition)) -> + spacesBeforeEnclosingDefinition)) when options.SuggestGeneratedOverrides -> let indent = max 1 (spacesBeforeOverrideKeyword - spacesBeforeEnclosingDefinition) - GetOverridableMethods - pos - ctx - enclosingTypeNameRange - (spacesBeforeOverrideKeyword + indent) - hasThis - isStatic - genBodyForOverriddenMeth + GetOverridableMethods pos ctx enclosingTypeNameRange (spacesBeforeOverrideKeyword + indent) hasThis isStatic options // Other completions | cc -> @@ -2004,7 +2065,8 @@ type internal TypeCheckInfo filterCtors, resolveOverloads, isInRangeOperator, - getAllSymbols + getAllSymbols, + options ) res |> Option.map (fun (items, denv, m) -> items, denv, completionContext, m) @@ -2022,7 +2084,7 @@ type internal TypeCheckInfo member _.GetVisibleNamespacesAndModulesAtPosition(cursorPos: pos) : ModuleOrNamespaceRef list = let (nenv, ad), m = GetBestEnvForPos cursorPos - GetVisibleNamespacesAndModulesAtPoint ncenv nenv OpenQualified m ad + GetVisibleNamespacesAndModulesAtPoint ncenv nenv OpenQualified m ad false /// Determines if a long ident is resolvable at a specific point. member _.IsRelativeNameResolvable(cursorPos: pos, plid: string list, item: Item) : bool = @@ -2051,9 +2113,7 @@ type internal TypeCheckInfo |> Option.map (fun (_, q, _, _) -> FSharpDisplayContext(fun _ -> q.DisplayEnv)) /// Get the auto-complete items at a location - member _.GetDeclarations - (parseResultsOpt, line, lineStr, partialName, completionContextAtPos, getAllEntities, genBodyForOverriddenMeth) - = + member _.GetDeclarations(parseResultsOpt, line, lineStr, partialName, completionContextAtPos, getAllEntities, options) = let isSigFile = SourceFileImpl.IsSignatureFile mainInputFileName DiagnosticsScope.Protect @@ -2073,7 +2133,7 @@ type internal TypeCheckInfo ResolveOverloads.Yes, completionContextAtPos, getAllEntities, - genBodyForOverriddenMeth + options ) match declItemsOpt with @@ -2114,7 +2174,9 @@ type internal TypeCheckInfo DeclarationListInfo.Error msg) /// Get the symbols for auto-complete items at a location - member _.GetDeclarationListSymbols(parseResultsOpt, line, lineStr, partialName, getAllEntities, genBodyForOverriddenMeth) = + member _.GetDeclarationListSymbols + (parseResultsOpt, line, lineStr, partialName, getAllEntities, genBodyForOverriddenMeth: FSharpCodeCompletionOptions) + = let isSigFile = SourceFileImpl.IsSignatureFile mainInputFileName DiagnosticsScope.Protect @@ -2316,7 +2378,7 @@ type internal TypeCheckInfo ResolveOverloads.Yes, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -2379,7 +2441,7 @@ type internal TypeCheckInfo ResolveOverloads.No, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -2426,7 +2488,7 @@ type internal TypeCheckInfo ResolveOverloads.No, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -2468,7 +2530,7 @@ type internal TypeCheckInfo ResolveOverloads.No, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -2505,7 +2567,7 @@ type internal TypeCheckInfo ResolveOverloads.Yes, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -2654,7 +2716,7 @@ type internal TypeCheckInfo ResolveOverloads.Yes, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -2684,7 +2746,7 @@ type internal TypeCheckInfo ResolveOverloads.Yes, None, (fun () -> []), - false + FSharpCodeCompletionOptions.Default ) match declItemsOpt with @@ -3363,27 +3425,21 @@ type FSharpCheckFileResults /// Intellisense autocompletions member _.GetDeclarationListInfo - (parsedFileResults, line, lineText, partialName, ?getAllEntities, ?completionContextAtPos, ?genBodyForOverriddenMeth) + (parsedFileResults, line, lineText, partialName, ?getAllEntities, ?completionContextAtPos, ?options: FSharpCodeCompletionOptions) = let getAllEntities = defaultArg getAllEntities (fun () -> []) - let genBodyForOverriddenMeth = defaultArg genBodyForOverriddenMeth true + let options = defaultArg options FSharpCodeCompletionOptions.Default match details with | None -> DeclarationListInfo.Empty | Some(scope, _builderOpt) -> - scope.GetDeclarations( - parsedFileResults, - line, - lineText, - partialName, - completionContextAtPos, - getAllEntities, - genBodyForOverriddenMeth - ) + scope.GetDeclarations(parsedFileResults, line, lineText, partialName, completionContextAtPos, getAllEntities, options) - member _.GetDeclarationListSymbols(parsedFileResults, line, lineText, partialName, ?getAllEntities, ?genBodyForOverriddenMeth) = + member _.GetDeclarationListSymbols(parsedFileResults, line, lineText, partialName, ?getAllEntities, ?options) = let getAllEntities = defaultArg getAllEntities (fun () -> []) - let genBodyForOverriddenMeth = defaultArg genBodyForOverriddenMeth true + + let genBodyForOverriddenMeth = + defaultArg options FSharpCodeCompletionOptions.Default match details with | None -> [] diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi index fedc323859f..6dfd5109b8d 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fsi +++ b/src/Compiler/Service/FSharpCheckerResults.fsi @@ -245,6 +245,14 @@ type public FSharpParsingOptions = static member internal FromTcConfigBuilder: tcConfigB: TcConfigBuilder * sourceFiles: string[] * isInteractive: bool -> FSharpParsingOptions +type public FSharpCodeCompletionOptions = + { SuggestPatternNames: bool + SuggestObsoleteSymbols: bool + SuggestGeneratedOverrides: bool + SuggestOverrideBodies: bool } + + static member Default: FSharpCodeCompletionOptions + /// A handle to the results of CheckFileInProject. [] type public FSharpCheckFileResults = @@ -293,8 +301,8 @@ type public FSharpCheckFileResults = /// /// Completion context for a particular position computed in advance. /// - /// - /// A switch to determine whether to generate a default implementation body for overridden method when completing. + /// + /// Options to allow customizing behavior by an IDE. /// member GetDeclarationListInfo: parsedFileResults: FSharpParseFileResults option * @@ -303,7 +311,7 @@ type public FSharpCheckFileResults = partialName: PartialLongName * ?getAllEntities: (unit -> AssemblySymbol list) * ?completionContextAtPos: (pos * CompletionContext option) * - ?genBodyForOverriddenMeth: bool -> + ?options: FSharpCodeCompletionOptions -> DeclarationListInfo /// Get the items for a declaration list in FSharpSymbol format @@ -324,8 +332,8 @@ type public FSharpCheckFileResults = /// /// Function that returns all entities from current and referenced assemblies. /// - /// - /// A switch to determine whether to generate a default implementation body for overridden method when completing. + /// + /// Options to allow customizing behavior by an IDE. /// member GetDeclarationListSymbols: parsedFileResults: FSharpParseFileResults option * @@ -333,7 +341,7 @@ type public FSharpCheckFileResults = lineText: string * partialName: PartialLongName * ?getAllEntities: (unit -> AssemblySymbol list) * - ?genBodyForOverriddenMeth: bool -> + ?options: FSharpCodeCompletionOptions -> FSharpSymbolUse list list /// Compute a formatted tooltip for the given keywords diff --git a/tests/FSharp.Compiler.Service.Tests/Checker.fs b/tests/FSharp.Compiler.Service.Tests/Checker.fs index fad035cd4ab..82b015f4bd1 100644 --- a/tests/FSharp.Compiler.Service.Tests/Checker.fs +++ b/tests/FSharp.Compiler.Service.Tests/Checker.fs @@ -125,8 +125,8 @@ module CheckResultsExtensions = member this.GetTooltip(context: ResolveContext, width) = this.GetToolTip(context.Pos.Line, context.Pos.Column, context.LineText, context.Names, FSharpTokenTag.Identifier, width) - member this.GetCodeCompletionSuggestions(context: CodeCompletionContext, parseResults: FSharpParseFileResults) = - this.GetDeclarationListInfo(Some parseResults, context.Pos.Line, context.LineText, context.PartialIdentifier) + member this.GetCodeCompletionSuggestions(context: CodeCompletionContext, parseResults: FSharpParseFileResults, options: FSharpCodeCompletionOptions) = + this.GetDeclarationListInfo(Some parseResults, context.Pos.Line, context.LineText, context.PartialIdentifier, options = options) [] module Checker = @@ -152,10 +152,13 @@ module Checker = let _, checkResults = getParseAndCheckResults context.Source context, checkResults - let getCompletionInfo (markedSource: string) = + let getCompletionInfoWithOptions (options: FSharpCodeCompletionOptions) (markedSource: string) = let context = getCompletionContext markedSource let parseResults, checkResults = getParseAndCheckResults context.Source - checkResults.GetCodeCompletionSuggestions(context, parseResults) + checkResults.GetCodeCompletionSuggestions(context, parseResults, options) + + let getCompletionInfo markedSource = + getCompletionInfoWithOptions FSharpCodeCompletionOptions.Default markedSource let getSymbolUses (markedSource: string) = let context, checkResults = getCheckedResolveContext markedSource diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index 6b875777538..d75f7e8e9fd 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -1,13 +1,21 @@ module FSharp.Compiler.Service.Tests.CompletionTests +open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices +open FSharp.Test.Assert +open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts open Xunit let private assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = - let itemNames = completionInfo.Items |> Array.map _.NameInCode |> set + let itemNames = + completionInfo.Items + |> Array.map _.NameInCode + |> Array.map normalizeNewLines + |> set for name in names do - Assert.True(Set.contains name itemNames = contains) + let name = normalizeNewLines name + Set.contains name itemNames |> shouldEqual contains let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = assertItemsWithNames true names completionInfo @@ -367,7 +375,356 @@ let ``Span appears in completion and is not marked obsolete`` () = let info = Checker.getCompletionInfo """ let test = System.Sp{caret} """ - // Verify that Span appears in completion when typing "System.Sp" - // and is not suppressed due to IsByRefLikeAttribute assertHasItemWithNames ["Span"] info #endif + +module Options = + let private assertItemWithOptions getOption (options: FSharpCodeCompletionOptions list) name source = + options + |> List.iter (fun options -> + let contains = getOption options + let info = Checker.getCompletionInfoWithOptions options source + assertItemsWithNames contains [name] info + ) + + module AllowObsolete = + let private allowObsoleteOptions = { FSharpCodeCompletionOptions.Default with SuggestObsoleteSymbols = true } + let private disallowObsoleteOptions = { FSharpCodeCompletionOptions.Default with SuggestObsoleteSymbols = false } + + let private assertItemWithOptions = + assertItemWithOptions _.SuggestObsoleteSymbols + + let assertItem (name: string) source = + assertItemWithOptions [allowObsoleteOptions; disallowObsoleteOptions] name source + + let assertItemAllowed name source = + assertItemWithOptions [allowObsoleteOptions] name source + + let assertItemNotAllowed name source = + assertItemWithOptions [disallowObsoleteOptions] name source + + [] + let ``Prop - Instance 01`` () = + assertItem "Prop" """ +type T() = + [] + member this.Prop = 1 + +T().{caret} +""" + + [] + let ``Prop - Instance 02`` () = + assertItem "Prop" """ +type T() = + [] + member this.Prop = 1 + +let t = T() +t.{caret} +""" + + [] + let ``Prop - Instance 03`` () = + assertItem "Prop" """ +type T() = + [] + member val Prop = 1 + +T().{caret} +""" + + [] + let ``Prop - Static 01`` () = + assertItemAllowed "Prop" """ +type T() = + [] + static member Prop = 1 + +T.{caret} +""" + + [] + let ``Prop - Static 02`` () = + assertItemAllowed "Prop" """ +type T() = + [] + static member val Prop = 1 + +T.{caret} +""" + + [] + let ``Prop - Extension 01`` () = + assertItemAllowed "Prop" """ +type System.String with + [] + member _.Prop = 1 + +"".{caret} +""" + + [] + let ``Prop - Extension 02`` () = + assertItemAllowed "Prop" """ +type System.String with + [] + static member Prop = 1 + +System.String.{caret} +""" + + [] + let ``Method - Instance 01`` () = + assertItem "Method" """ +type T() = + [] + member _.Method() = 1 + +T().{caret} +""" + + [] + let ``Method - Instance 02`` () = + assertItem "Method" """ +type T() = + [] + member _.Method() = 1 + +let t = T() +t.{caret} +""" + + [] + let ``Method - Static 01`` () = + assertItemAllowed "Method" """ +type T() = + [] + static member Method() = 1 + +T.{caret} +""" + + [] + let ``Union 01`` () = + assertItemAllowed "A" """ +[] +type T = + | A + +T.{caret} +""" + + [] + let ``Module - Value 01`` () = + assertItemAllowed "x" """ +[] +let x = 1 + +{caret} +""" + [] + let ``Module - Value 02`` () = + assertItemAllowed "x" """ +[] +let x = 1 + +do + {caret} +""" + [] + let ``Module - Value 03`` () = + assertItemAllowed "x" """ +module Module1 = + [] + let x = 1 + +module Module2 = + do Module1.{caret} +""" + + [] + let ``Module - Value 04`` () = + assertItemAllowed "x" """ +module Module1 = + [] + let x = 1 + +module Module2 = + open Module1 + do {caret} +""" + + [] + let ``Module - Value 05`` () = + assertItemAllowed "x" """ +[] +let x = 1 + +x{caret} +""" + [] + let ``Module - Value 06`` () = + assertItemAllowed "x" """ +[] +let x = 1 + +do + x{caret} +""" + [] + let ``Module - Value 07`` () = + assertItemAllowed "x" """ +module Module1 = + [] + let x = 1 + +module Module2 = + do Module1.x{caret} +""" + + [] + let ``Module - Value 08`` () = + assertItemAllowed "x" """ +module Module1 = + [] + let x = 1 + +module Module2 = + open Module1 + do x{caret} +""" + + [] + let ``Type 01`` () = + assertItemAllowed "T" """ +[] +type T() = + class end + +let _: {caret} +""" + + [] + let ``Type 02`` () = + assertItemAllowed "T" """ +[] +type T() = + class end + +{caret} +""" + + [] + let ``Type 03`` () = + assertItemAllowed "T" """ +[] +type T() = + class end + +do {caret} +""" + + [] + let ``Record - Field 01`` () = + assertItemAllowed "F" """ +type R = + { [] + F: int } + +let r = { {caret} } +""" + + [] + let ``Record - Field 02`` () = + assertItemAllowed "F" """ +[] +type R = + { F: int } + +let r = { {caret} } +""" + + [] + let ``Record - Field 03`` () = + assertItemAllowed "F" """ +[] +type R = + { F: int } + +let r: R = { F = 1 } +r.{caret} +""" + + [] + let ``Exception 01`` () = + assertItemAllowed "E" """ +[] +exception E + +{caret} +""" + [] + let ``Exception 02`` () = + assertItemAllowed "E" """ +[] +exception E + +E{caret} +""" + + [] + let ``Exception 03`` () = + assertItemAllowed "E" """ +[] +exception E + +try () with {caret} +""" + + [] + let ``Exception 04`` () = + assertItemAllowed "E" """ +[] +exception E + +try () with E{caret} +""" + + + module PatternNameSuggestions = + let private suggestPatternNames = { FSharpCodeCompletionOptions.Default with SuggestPatternNames = true } + let private doNotSuggestPatternNames = { FSharpCodeCompletionOptions.Default with SuggestPatternNames = false } + + let assertItemWithOptions = + assertItemWithOptions _.SuggestPatternNames + + let assertItem name source = + assertItemWithOptions [suggestPatternNames; doNotSuggestPatternNames] name source + + [] + let ``Union case field 01`` () = + assertItem "named" """ +type U = + | A of named: int + +match A 1 with +| A n{caret} +""" + + module OverrideSuggestions = + let private suggestOverrides = { FSharpCodeCompletionOptions.Default with SuggestGeneratedOverrides = true } + let private doNotSuggestOverrides = { FSharpCodeCompletionOptions.Default with SuggestGeneratedOverrides = false } + + let assertItemWithOptions = + assertItemWithOptions _.SuggestGeneratedOverrides + + let assertItem name source = + assertItemWithOptions [suggestOverrides; doNotSuggestOverrides] name source + + [] + let ``Override 01`` () = + assertItem "this.ToString (): string = \n base.ToString()" """ +type T() = + override {caret} +""" \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index b7994bed3ae..e2aaca46ac3 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -2066,7 +2066,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.CodeAnalysi FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.CodeAnalysis.FSharpSymbolUse[] GetUsesOfSymbolInFile(FSharp.Compiler.Symbols.FSharpSymbol, Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Diagnostics.FSharpDiagnostic[] Diagnostics FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Diagnostics.FSharpDiagnostic[] get_Diagnostics() -FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.EditorServices.DeclarationListInfo GetDeclarationListInfo(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults], Int32, System.String, FSharp.Compiler.EditorServices.PartialLongName, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.AssemblySymbol]]], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Position,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.CompletionContext]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.EditorServices.DeclarationListInfo GetDeclarationListInfo(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults], Int32, System.String, FSharp.Compiler.EditorServices.PartialLongName, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.AssemblySymbol]]], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Position,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.EditorServices.CompletionContext]]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.EditorServices.FindDeclResult GetDeclarationLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.EditorServices.MethodGroup GetMethods(Int32, Int32, System.String, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.String]]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.EditorServices.SemanticClassificationItem[] GetSemanticClassification(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) @@ -2079,7 +2079,7 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSh FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Symbols.FSharpOpenDeclaration[] get_OpenDeclarations() FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: FSharp.Compiler.Text.Range[] GetFormatSpecifierLocations() FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetSymbolUsesAtLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String]) -FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse]] GetDeclarationListSymbols(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults], Int32, System.String, FSharp.Compiler.EditorServices.PartialLongName, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.AssemblySymbol]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse]] GetDeclarationListSymbols(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpParseFileResults], Int32, System.String, FSharp.Compiler.EditorServices.PartialLongName, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.EditorServices.AssemblySymbol]]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.FSharpSymbolUse] GetSymbolUseAtLocation(Int32, Int32, System.String, Microsoft.FSharp.Collections.FSharpList`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpDisplayContext] GetDisplayContextForPos(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpCheckFileResults: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Symbols.FSharpDisplayContext] TryGetCapturedDisplayContext(FSharp.Compiler.Text.Range) @@ -2163,6 +2163,27 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesA FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharpProjectSnapshot, Microsoft.FSharp.Core.FSharpOption`1[System.String]) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean Equals(FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean Equals(System.Object) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean SuggestGeneratedOverrides +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean SuggestObsoleteSymbols +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean SuggestOverrideBodies +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean SuggestPatternNames +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean get_SuggestGeneratedOverrides() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean get_SuggestObsoleteSymbols() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean get_SuggestOverrideBodies() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Boolean get_SuggestPatternNames() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions Default +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions get_Default() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Int32 CompareTo(FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Int32 CompareTo(System.Object) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Int32 GetHashCode() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: System.String ToString() +FSharp.Compiler.CodeAnalysis.FSharpCodeCompletionOptions: Void .ctor(Boolean, Boolean, Boolean, Boolean) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionContainedInACurriedParameter(FSharp.Compiler.Text.Position) diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index de1ed80a03c..fa7db6ec835 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -182,6 +182,11 @@ type internal FSharpCompletionProvider let completionContext = ParsedInput.TryGetCompletionContext(completionContextPos, parseResults.ParseTree, line) + let options = + { FSharpCodeCompletionOptions.Default with + SuggestOverrideBodies = genBodyForOverriddenMeth + } + let declarations = checkFileResults.GetDeclarationListInfo( Some(parseResults), @@ -190,7 +195,7 @@ type internal FSharpCompletionProvider partialName, getAllSymbols, (completionContextPos, completionContext), - genBodyForOverriddenMeth + options ) let results = List()