Skip to content

Commit

Permalink
open static classes feature
Browse files Browse the repository at this point in the history
  • Loading branch information
dsyme committed Jul 4, 2019
1 parent b26941b commit 607fa35
Show file tree
Hide file tree
Showing 14 changed files with 364 additions and 203 deletions.
8 changes: 4 additions & 4 deletions src/fsharp/ErrorLogger.fs
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ type public FSharpErrorSeverityOptions =


// See https://github.com/Microsoft/visualfsharp/issues/6417, if a compile of the FSharp.Compiler.Services.dll or other compiler
// binary produces exactly 65536 methods then older versions of the compiler raise a bug. If you hit this bug again then try removing
// this.
let dummyMethodFOrBug6417A() = ()
let dummyMethodFOrBug6417B() = ()
// binary produces exactly 65536 methods then older versions of the compiler raise a bug. If you hit this bug again then try adding
// this back in.
// let dummyMethodFOrBug6417A() = ()
// let dummyMethodFOrBug6417B() = ()
1 change: 1 addition & 0 deletions src/fsharp/ExtensionTyping.fs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ module internal ExtensionTyping =
member __.IsEnum = x.IsEnum
member __.IsClass = x.IsClass
member __.IsSealed = x.IsSealed
member __.IsAbstract = x.IsAbstract
member __.IsInterface = x.IsInterface
member __.GetArrayRank() = x.GetArrayRank()
member __.GenericParameterPosition = x.GenericParameterPosition
Expand Down
1 change: 1 addition & 0 deletions src/fsharp/ExtensionTyping.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ module internal ExtensionTyping =
member IsInterface : bool
member IsClass : bool
member IsSealed : bool
member IsAbstract : bool
member IsPublic : bool
member IsNestedPublic : bool
member GenericParameterPosition : int
Expand Down
416 changes: 248 additions & 168 deletions src/fsharp/NameResolution.fs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/fsharp/NameResolution.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ val internal AddModuleOrNamespaceRefsToNameEnv : TcGlobals ->
val internal AddModuleOrNamespaceRefToNameEnv : TcGlobals -> ImportMap -> range -> bool -> AccessorDomain -> NameResolutionEnv -> ModuleOrNamespaceRef -> NameResolutionEnv

/// Add a list of modules or namespaces to the name resolution environment
val internal AddModulesAndNamespacesContentsToNameEnv : TcGlobals -> ImportMap -> AccessorDomain -> range -> bool -> NameResolutionEnv -> ModuleOrNamespaceRef list -> NameResolutionEnv
val internal AddEntitiesContentsToNameEnv : TcGlobals -> ImportMap -> AccessorDomain -> range -> bool -> NameResolutionEnv -> ModuleOrNamespaceRef list -> NameResolutionEnv

/// A flag which indicates if it is an error to have two declared type parameters with identical names
/// in the name resolution environment.
Expand Down Expand Up @@ -468,8 +468,8 @@ type PermitDirectReferenceToGeneratedType =
| Yes
| No

/// Resolve a long identifier to a namespace or module.
val internal ResolveLongIndentAsModuleOrNamespace : TcResultsSink -> ResultCollectionSettings -> Import.ImportMap -> range -> bool -> FullyQualifiedFlag -> NameResolutionEnv -> AccessorDomain -> Ident -> Ident list -> isOpenDecl: bool -> ResultOrException<(int * ModuleOrNamespaceRef * ModuleOrNamespaceType) list >
/// Resolve a long identifier to a namespace, module or static class.
val internal ResolveLongIndentAsModuleOrNamespaceOrStaticClass : TcResultsSink -> ResultCollectionSettings -> Import.ImportMap -> range -> allowStaticClasses: bool -> first: bool -> FullyQualifiedFlag -> NameResolutionEnv -> AccessorDomain -> Ident -> Ident list -> isOpenDecl: bool -> ResultOrException<(int * ModuleOrNamespaceRef * ModuleOrNamespaceType) list >

/// Resolve a long identifier to an object constructor.
val internal ResolveObjectConstructor : NameResolver -> DisplayEnv -> range -> AccessorDomain -> TType -> ResultOrException<Item>
Expand Down
16 changes: 16 additions & 0 deletions src/fsharp/TastOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8940,3 +8940,19 @@ let isThreadOrContextStatic g attrs =
let mkUnitDelayLambda (g: TcGlobals) m e =
let uv, _ = mkCompGenLocal m "unitVar" g.unit_ty
mkLambda m uv (e, tyOfExpr g e)


let isStaticClass (g:TcGlobals) (x: EntityRef) =
not x.IsModuleOrNamespace &&
x.TyparsNoRange.IsEmpty &&
((x.IsILTycon &&
x.ILTyconRawMetadata.IsSealed &&
x.ILTyconRawMetadata.IsAbstract)
#if !NO_EXTENSIONTYPING
|| (x.IsProvided &&
match x.TypeReprInfo with
| TProvidedTypeExtensionPoint info -> info.IsSealed && info.IsAbstract
| _ -> false)
#endif
|| (not x.IsILTycon && not x.IsProvided && HasFSharpAttribute g g.attrib_AbstractClassAttribute x.Attribs)) &&
not (HasFSharpAttribute g g.attrib_RequireQualifiedAccessAttribute x.Attribs)
1 change: 1 addition & 0 deletions src/fsharp/TastOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -2295,3 +2295,4 @@ val isThreadOrContextStatic: TcGlobals -> Attrib list -> bool

val mkUnitDelayLambda: TcGlobals -> range -> Expr -> Expr

val isStaticClass: g: TcGlobals -> tcref: TyconRef -> bool
28 changes: 14 additions & 14 deletions src/fsharp/TypeChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -370,11 +370,11 @@ let AddLocalTyconsAndReport tcSink scopem g amap m tycons env =
CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights)
env

/// Adjust the TcEnv to account for opening the set of modules and namespaces implied by an `open` declaration
let OpenModulesOrNamespaces tcSink g amap scopem root env mvvs openDeclaration =
/// Adjust the TcEnv to account for opening the set of modules, namespaces or static classes implied by an `open` declaration
let OpenEntities tcSink g amap scopem root env mvvs openDeclaration =
let env =
if isNil mvvs then env else
{ env with eNameResEnv = AddModulesAndNamespacesContentsToNameEnv g amap env.eAccessRights scopem root env.eNameResEnv mvvs }
{ env with eNameResEnv = AddEntitiesContentsToNameEnv g amap env.eAccessRights scopem root env.eNameResEnv mvvs }
CallEnvSink tcSink (scopem, env.NameEnv, env.eAccessRights)
CallOpenDeclarationSink tcSink openDeclaration
env
Expand Down Expand Up @@ -644,11 +644,11 @@ let ImplicitlyOpenOwnNamespace tcSink g amap scopem enclosingNamespacePath env =
match enclosingNamespacePathToOpen with
| id :: rest ->
let ad = env.eAccessRights
match ResolveLongIndentAsModuleOrNamespace tcSink ResultCollectionSettings.AllResults amap scopem true OpenQualified env.eNameResEnv ad id rest true with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass tcSink ResultCollectionSettings.AllResults amap scopem true true OpenQualified env.eNameResEnv ad id rest true with
| Result modrefs ->
let modrefs = List.map p23 modrefs
let openDecl = OpenDeclaration.Create (enclosingNamespacePathToOpen, modrefs, scopem, true)
OpenModulesOrNamespaces tcSink g amap scopem false env modrefs openDecl
OpenEntities tcSink g amap scopem false env modrefs openDecl
| Exception _ -> env
| _ -> env

Expand Down Expand Up @@ -6892,7 +6892,7 @@ and TcConstExpr cenv overallTy env m tpenv c =
let expr =
let modName = "NumericLiteral" + suffix
let ad = env.eAccessRights
match ResolveLongIndentAsModuleOrNamespace cenv.tcSink ResultCollectionSettings.AtMostOneResult cenv.amap m true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AtMostOneResult cenv.amap m true true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false with
| Result []
| Exception _ -> error(Error(FSComp.SR.tcNumericLiteralRequiresModule modName, m))
| Result ((_, mref, _) :: _) ->
Expand Down Expand Up @@ -8719,7 +8719,7 @@ and TcNameOfExpr cenv env tpenv (synArg: SynExpr) =
| LongOrSingleIdent (false, (LongIdentWithDots(longId, _) as lidd), _, _) when longId.Length > 0 ->
let ad = env.eAccessRights
let id, rest = List.headAndTail longId
match ResolveLongIndentAsModuleOrNamespace cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m true OpenQualified env.eNameResEnv ad id rest true with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m false true OpenQualified env.eNameResEnv ad id rest true with
| Result modref when delayed.IsEmpty && modref |> List.exists (p23 >> IsEntityAccessible cenv.amap m ad) ->
() // resolved to a module or namespace, done with checks
| _ ->
Expand Down Expand Up @@ -12586,19 +12586,19 @@ let TcTyconMemberSpecs cenv env containerInfo declKind tpenv (augSpfn: SynMember
// Bind 'open' declarations
//-------------------------------------------------------------------------

let TcModuleOrNamespaceLidAndPermitAutoResolve tcSink env amap (longId: Ident list) =
let TcOpenLidAndPermitAutoResolve tcSink env amap (longId : Ident list) =
let ad = env.eAccessRights
match longId with
| [] -> []
| id :: rest ->
let m = longId |> List.map (fun id -> id.idRange) |> List.reduce unionRanges
match ResolveLongIndentAsModuleOrNamespace tcSink ResultCollectionSettings.AllResults amap m true OpenQualified env.eNameResEnv ad id rest true with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass tcSink ResultCollectionSettings.AllResults amap m true true OpenQualified env.eNameResEnv ad id rest true with
| Result res -> res
| Exception err ->
errorR(err); []

let TcOpenDecl tcSink (g: TcGlobals) amap m scopem env (longId: Ident list) =
match TcModuleOrNamespaceLidAndPermitAutoResolve tcSink env amap longId with
match TcOpenLidAndPermitAutoResolve tcSink env amap longId with
| [] -> env
| modrefs ->

Expand Down Expand Up @@ -12650,7 +12650,7 @@ let TcOpenDecl tcSink (g: TcGlobals) amap m scopem env (longId: Ident list) =
modrefs |> List.iter (fun modref -> CheckEntityAttributes g modref m |> CommitOperationResult)

let openDecl = OpenDeclaration.Create (longId, modrefs, scopem, false)
let env = OpenModulesOrNamespaces tcSink g amap scopem false env modrefs openDecl
let env = OpenEntities tcSink g amap scopem false env modrefs openDecl
env


Expand Down Expand Up @@ -14125,7 +14125,7 @@ module MutRecBindingChecking =
let resolved =
match p with
| [] -> Result []
| id :: rest -> ResolveLongIndentAsModuleOrNamespace cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m true OpenQualified env.eNameResEnv ad id rest false
| id :: rest -> ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m false true OpenQualified env.eNameResEnv ad id rest false
let mvvs = ForceRaise resolved
if isNil mvvs then env else
let modrefs = mvvs |> List.map p23
Expand Down Expand Up @@ -16952,7 +16952,7 @@ let rec TcSignatureElementNonMutRec cenv parent typeNames endm (env: TcEnv) synS
let resolved =
match p with
| [] -> Result []
| id :: rest -> ResolveLongIndentAsModuleOrNamespace cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m true OpenQualified env.eNameResEnv ad id rest false
| id :: rest -> ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m false true OpenQualified env.eNameResEnv ad id rest false
let mvvs = ForceRaise resolved
let scopem = unionRanges m endm
let unfilteredModrefs = mvvs |> List.map p23
Expand Down Expand Up @@ -17506,7 +17506,7 @@ let ApplyAssemblyLevelAutoOpenAttributeToTcEnv g amap (ccu: CcuThunk) scopem env
| ValueNone -> warn()
| ValueSome _ ->
let openDecl = OpenDeclaration.Create ([], [modref], scopem, false)
OpenModulesOrNamespaces TcResultsSink.NoSink g amap scopem root env [modref] openDecl
OpenEntities TcResultsSink.NoSink g amap scopem root env [modref] openDecl

// Add the CCU and apply the "AutoOpen" attributes
let AddCcuToTcEnv(g, amap, scopem, env, assemblyName, ccu, autoOpens, internalsVisible) =
Expand Down
6 changes: 5 additions & 1 deletion src/fsharp/tast.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1446,7 +1446,10 @@ and
IsSealed: bool

/// A flag read eagerly from the provided type and used to compute basic properties of the type definition.
IsInterface: bool
IsAbstract: bool

/// A flag read eagerly from the provided type and used to compute basic properties of the type definition.
IsInterface: bool

/// A flag read eagerly from the provided type and used to compute basic properties of the type definition.
IsStructOrEnum: bool
Expand Down Expand Up @@ -2009,6 +2012,7 @@ and Construct =
IsStructOrEnum = st.PUntaint((fun st -> st.IsValueType || st.IsEnum), m)
IsInterface = st.PUntaint((fun st -> st.IsInterface), m)
IsSealed = st.PUntaint((fun st -> st.IsSealed), m)
IsAbstract = st.PUntaint((fun st -> st.IsAbstract), m)
IsClass = st.PUntaint((fun st -> st.IsClass), m)
IsErased = isErased
IsSuppressRelocate = isSuppressRelocate }
Expand Down
2 changes: 1 addition & 1 deletion tests/EndToEndBuildTests/ProvidedTypes/ProvidedTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4026,7 +4026,7 @@ namespace ProviderImplementation.ProvidedTypes.AssemblyReader
// Emit compressed untagged integer
member buf.EmitZUntaggedIndex big idx =
if big then buf.EmitInt32 idx
elif idx > 0xffff then failwith "EmitZUntaggedIndex: too big for small address or simple index"
elif idx > 0xffff then failwithf "EmitZUntaggedIndex: too big for small address or simple index, idx = %d, big = %A, stack = %s" idx big ((new System.Diagnostics.StackTrace()).ToString())
else buf.EmitInt32AsUInt16 idx

// Emit compressed tagged integer
Expand Down
60 changes: 60 additions & 0 deletions tests/fsharp/core/longnames/test.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,66 @@ module rec Ok23 =

test "lkneecec09iew23" (typeof<A.Dummy>.FullName.Contains("AModule") )


[<AbstractClass; Sealed>]
type MyMath() =
static member Min(a: double, b: double) = System.Math.Min(a, b)
static member Min(a: int, b: int) = System.Math.Min(a, b)

[<AbstractClass; Sealed; AutoOpen>]
type AutoOpenMyMath() =
static member AutoMin(a: double, b: double) = System.Math.Min(a, b)
static member AutoMin(a: int, b: int) = System.Math.Min(a, b)

[<AbstractClass; Sealed; RequireQualifiedAccess>]
type NotAllowedToOpen() =
static member QualifiedMin(a: double, b: double) = System.Math.Min(a, b)
static member QualifiedMin(a: int, b: int) = System.Math.Min(a, b)

module OpenSystemMathOnce =

open System.Math
let x = Min(1.0, 2.0)
test "vwejhweoiu" (x = 1.0)


module OpenSystemMathTwice =

open System.Math
let x = Min(1.0, 2.0)

open System.Math
let x2 = Min(2.0, 1.0)

test "vwejhweoiu2" (x2 = 1.0)

module OpenMyMathOnce =

open MyMath
let x = Min(1.0, 2.0)
let x2 = Min(1, 2)

test "vwejhweoiu2" (x = 1.0)
test "vwejhweoiu3" (x2 = 1)

module DontOpenAutoMath =

let x = AutoMin(1.0, 2.0)
let x2 = AutoMin(1, 2)

test "vwejhweoiu2" (x = 1.0)
test "vwejhweoiu3" (x2 = 1)

module OpenAutoMath =
open AutoOpenMyMath
//open NotAllowedToOpen

let x = AutoMin(1.0, 2.0)
let x2 = AutoMin(1, 2)

test "vwejhweoiu2" (x = 1.0)
test "vwejhweoiu3" (x2 = 1)

#if TESTS_AS_APP
let RUN() = !failures
#else
Expand Down
10 changes: 0 additions & 10 deletions tests/service/EditorTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,16 +1288,6 @@ let ``Test TPProject param info`` () =

#endif // TEST_TP_PROJECTS

#if EXE

``Intro test`` ()
//``Test TPProject all symbols`` ()
//``Test TPProject errors`` ()
//``Test TPProject quick info`` ()
//``Test TPProject param info`` ()
``Basic cancellation test`` ()
``Intro test`` ()
#endif

[<Test>]
let ``FSharpField.IsNameGenerated`` () =
Expand Down
8 changes: 8 additions & 0 deletions vsintegration/tests/UnitTests/CompletionProviderTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,14 @@ List().
"ExtensionMeth"]
VerifyCompletionListExactly(fileContents, "List().", expected)

[<Test>]
let ``Completion for open contains namespaces and static types``() =
let fileContents = """
open System.Ma
"""
let expected = ["Management"; "Math"] // both namespace and static type
VerifyCompletionList(fileContents, "System.Ma", expected, [])

[<Test>]
let ``No completion on type name at declaration site``() =
let fileContents = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3639,8 +3639,8 @@ let x = query { for bbbb in abbbbc(*D0*) do
AssertAutoCompleteContains
[ "open System." ]
"." // marker
[ "Collections" ] // should contain (namespace)
[ "Console" ] // should not contain (type)
[ "Collections"; "Console" ] // should contain (namespace, static type)
[ "Int32" ] // should not contain (non-static type)

[<Test>]
member public this.``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case2``() =
Expand Down

0 comments on commit 607fa35

Please sign in to comment.