Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add langver support and tests for open static classes language feature
  • Loading branch information
KevinRansom committed Jul 11, 2019
commit 5c0bb18f691a081d7c5be5fc3465371e7b90492d
3 changes: 1 addition & 2 deletions src/fsharp/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type LanguageFeature =
| RelaxWhitespace = 4
| NameOf = 5
| ImplicitYield = 6

| OpenStaticClasses = 7

/// LanguageVersion management
type LanguageVersion (specifiedVersion) =
Expand All @@ -51,7 +51,6 @@ type LanguageVersion (specifiedVersion) =
LanguageFeature.WildCardInForLoop, previewVersion
LanguageFeature.RelaxWhitespace, previewVersion
LanguageFeature.NameOf, previewVersion
LanguageFeature.ImplicitYield, previewVersion
|]

let specified =
Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type LanguageFeature =
| RelaxWhitespace = 4
| NameOf = 5
| ImplicitYield = 6

| OpenStaticClasses = 7

/// LanguageVersion management
type LanguageVersion =
Expand Down
65 changes: 36 additions & 29 deletions src/fsharp/NameResolution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -756,29 +756,33 @@ let AddUnionCases2 bulkAddMode (eUnqualifiedItems: UnqualifiedItems) (ucrefs: Un
let item = Item.UnionCase(GeneralizeUnionCaseRef ucref, false)
acc.Add (ucref.CaseName, item))

let AddStaticContentOfTyconRefToNameEnv (g:TcGlobals) (amap: Import.ImportMap) m (nenv: NameResolutionEnv) (tcref:TyconRef) =
let ty = generalizedTyconRef tcref
let infoReader = InfoReader(g,amap)
let items =
[| let methGroups =
AllMethInfosOfTypeInScope ResultCollectionSettings.AllResults infoReader nenv None AccessorDomain.AccessibleFromSomeFSharpCode PreferOverrides m ty
|> List.groupBy (fun m -> m.LogicalName)

for (methName, methGroup) in methGroups do
let methGroup = methGroup |> List.filter (fun m -> not m.IsInstance && not m.IsClassConstructor)
if not methGroup.IsEmpty then
yield KeyValuePair(methName, Item.MethodGroup(methName, methGroup, None))
let AddStaticContentOfTyconRefToNameEnv (g:TcGlobals) (amap: Import.ImportMap) m (nenv: NameResolutionEnv) (tcref:TyconRef) =
// If OpenStaticClasses is not enabled then don't do this
if g.langVersion.SupportsFeature LanguageFeature.OpenStaticClasses then
let ty = generalizedTyconRef tcref
let infoReader = InfoReader(g,amap)
let items =
[| let methGroups =
AllMethInfosOfTypeInScope ResultCollectionSettings.AllResults infoReader nenv None AccessorDomain.AccessibleFromSomeFSharpCode PreferOverrides m ty
|> List.groupBy (fun m -> m.LogicalName)

for (methName, methGroup) in methGroups do
let methGroup = methGroup |> List.filter (fun m -> not m.IsInstance && not m.IsClassConstructor)
if not methGroup.IsEmpty then
yield KeyValuePair(methName, Item.MethodGroup(methName, methGroup, None))

let propInfos =
AllPropInfosOfTypeInScope ResultCollectionSettings.AllResults infoReader nenv None AccessorDomain.AccessibleFromSomeFSharpCode PreferOverrides m ty
|> List.groupBy (fun m -> m.PropertyName)
let propInfos =
AllPropInfosOfTypeInScope ResultCollectionSettings.AllResults infoReader nenv None AccessorDomain.AccessibleFromSomeFSharpCode PreferOverrides m ty
|> List.groupBy (fun m -> m.PropertyName)

for (propName, propInfos) in propInfos do
let propInfos = propInfos |> List.filter (fun m -> m.IsStatic)
for propInfo in propInfos do
yield KeyValuePair(propName , Item.Property(propName,[propInfo])) |]
for (propName, propInfos) in propInfos do
let propInfos = propInfos |> List.filter (fun m -> m.IsStatic)
for propInfo in propInfos do
yield KeyValuePair(propName , Item.Property(propName,[propInfo])) |]

{ nenv with eUnqualifiedItems = nenv.eUnqualifiedItems.AddAndMarkAsCollapsible items }
{ nenv with eUnqualifiedItems = nenv.eUnqualifiedItems.AddAndMarkAsCollapsible items }
else
nenv

/// Add any implied contents of a type definition to the environment.
let private AddPartsOfTyconRefToNameEnv bulkAddMode ownDefinition (g: TcGlobals) amap m nenv (tcref: TyconRef) =
Expand Down Expand Up @@ -1992,13 +1996,16 @@ let CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities
//-------------------------------------------------------------------------

/// Perform name resolution for an identifier which must resolve to be a namespace or module.
let rec ResolveLongIndentAsModuleOrNamespaceOrStaticClass sink (atMostOne: ResultCollectionSettings) amap m allowStaticClasses first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl =
let rec ResolveLongIndentAsModuleOrNamespaceOrStaticClass (g: TcGlobals) sink (atMostOne: ResultCollectionSettings) amap m allowStaticClasses first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl =

// If the selected language version doesn't support open static classes then turn them off.
let allowStaticClasses = allowStaticClasses && g.langVersion.SupportsFeature LanguageFeature.OpenStaticClasses
if first && id.idText = MangledGlobalName then
match rest with
| [] ->
error (Error(FSComp.SR.nrGlobalUsedOnlyAsFirstName(), id.idRange))
| id2 :: rest2 ->
ResolveLongIndentAsModuleOrNamespaceOrStaticClass sink atMostOne amap m allowStaticClasses false FullyQualified nenv ad id2 rest2 isOpenDecl
ResolveLongIndentAsModuleOrNamespaceOrStaticClass g sink atMostOne amap m allowStaticClasses false FullyQualified nenv ad id2 rest2 isOpenDecl
else
let moduleOrNamespaces = nenv.ModulesAndNamespaces fullyQualified
let namespaceNotFound = lazy(
Expand Down Expand Up @@ -2093,8 +2100,8 @@ let rec ResolveLongIndentAsModuleOrNamespaceOrStaticClass sink (atMostOne: Resul
else
raze (namespaceNotFound.Force())

let ResolveLongIndentAsModuleOrNamespaceThen sink atMostOne amap m fullyQualified (nenv: NameResolutionEnv) ad id rest isOpenDecl f =
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass sink ResultCollectionSettings.AllResults amap m false true fullyQualified nenv ad id [] isOpenDecl with
let ResolveLongIndentAsModuleOrNamespaceThen g sink atMostOne amap m fullyQualified (nenv: NameResolutionEnv) ad id rest isOpenDecl f =
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass g sink ResultCollectionSettings.AllResults amap m false true fullyQualified nenv ad id [] isOpenDecl with
| Result modrefs ->
match rest with
| [] -> error(Error(FSComp.SR.nrUnexpectedEmptyLongId(), id.idRange))
Expand Down Expand Up @@ -2610,7 +2617,7 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified
// Otherwise modules are searched first. REVIEW: modules and types should be searched together.
// For each module referenced by 'id', search the module as if it were an F# module and/or a .NET namespace.
let moduleSearch ad () =
ResolveLongIndentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest isOpenDecl
ResolveLongIndentAsModuleOrNamespaceThen ncenv.g sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest isOpenDecl
(ResolveExprLongIdentInModuleOrNamespace ncenv nenv typeNameResInfo ad)

// REVIEW: somewhat surprisingly, this shows up on performance traces, with tcrefs non-nil.
Expand Down Expand Up @@ -2794,7 +2801,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa
// Long identifiers in patterns
else
let moduleSearch ad () =
ResolveLongIndentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest false
ResolveLongIndentAsModuleOrNamespaceThen ncenv.g sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest false
(ResolvePatternLongIdentInModuleOrNamespace ncenv nenv numTyArgsOpt ad)

let tyconSearch ad =
Expand Down Expand Up @@ -3006,12 +3013,12 @@ let rec ResolveTypeLongIdentPrim sink (ncenv: NameResolver) occurence first full
NoResultsOrUsefulErrors

let modulSearch =
ResolveLongIndentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv ad id rest false
ResolveLongIndentAsModuleOrNamespaceThen ncenv.g sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv ad id rest false
(ResolveTypeLongIdentInModuleOrNamespace sink nenv ncenv typeNameResInfo ad genOk)
|?> List.concat

let modulSearchFailed() =
ResolveLongIndentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv AccessibleFromSomeFSharpCode id rest false
ResolveLongIndentAsModuleOrNamespaceThen ncenv.g sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv AccessibleFromSomeFSharpCode id rest false
(ResolveTypeLongIdentInModuleOrNamespace sink nenv ncenv typeNameResInfo.DropStaticArgsInfo AccessibleFromSomeFSharpCode genOk)
|?> List.concat

Expand Down Expand Up @@ -3212,7 +3219,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi
match lid with
| [] -> NoResultsOrUsefulErrors
| id2 :: rest2 ->
ResolveLongIndentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m OpenQualified nenv ad id2 rest2 false
ResolveLongIndentAsModuleOrNamespaceThen ncenv.g sink ResultCollectionSettings.AtMostOneResult ncenv.amap m OpenQualified nenv ad id2 rest2 false
(ResolveFieldInModuleOrNamespace ncenv nenv ad)

let resInfo, item, rest =
Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/NameResolution.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ type PermitDirectReferenceToGeneratedType =
| No

/// 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 >
val internal ResolveLongIndentAsModuleOrNamespaceOrStaticClass : TcGlobals -> 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: 8 additions & 8 deletions src/fsharp/TypeChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ let ImplicitlyOpenOwnNamespace tcSink g amap scopem enclosingNamespacePath env =
match enclosingNamespacePathToOpen with
| id :: rest ->
let ad = env.eAccessRights
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass tcSink ResultCollectionSettings.AllResults amap scopem true true OpenQualified env.eNameResEnv ad id rest true with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass g 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)
Expand Down Expand Up @@ -6966,7 +6966,7 @@ and TcConstExpr cenv overallTy env m tpenv c =
let expr =
let modName = "NumericLiteral" + suffix
let ad = env.eAccessRights
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AtMostOneResult cenv.amap m true true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.g 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 @@ -8837,7 +8837,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 ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m false true OpenQualified env.eNameResEnv ad id rest true with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.g 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 @@ -12705,19 +12705,19 @@ let TcTyconMemberSpecs cenv env containerInfo declKind tpenv (augSpfn: SynMember
// Bind 'open' declarations
//-------------------------------------------------------------------------

let TcOpenLidAndPermitAutoResolve tcSink env amap (longId : Ident list) =
let TcOpenLidAndPermitAutoResolve g 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 ResolveLongIndentAsModuleOrNamespaceOrStaticClass tcSink ResultCollectionSettings.AllResults amap m true true OpenQualified env.eNameResEnv ad id rest true with
match ResolveLongIndentAsModuleOrNamespaceOrStaticClass g 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 TcOpenLidAndPermitAutoResolve tcSink env amap longId with
match TcOpenLidAndPermitAutoResolve g tcSink env amap longId with
| [] -> env
| modrefs ->

Expand Down Expand Up @@ -14244,7 +14244,7 @@ module MutRecBindingChecking =
let resolved =
match p with
| [] -> Result []
| id :: rest -> ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m false true OpenQualified env.eNameResEnv ad id rest false
| id :: rest -> ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.g 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 @@ -17071,7 +17071,7 @@ let rec TcSignatureElementNonMutRec cenv parent typeNames endm (env: TcEnv) synS
let resolved =
match p with
| [] -> Result []
| id :: rest -> ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.tcSink ResultCollectionSettings.AllResults cenv.amap m false true OpenQualified env.eNameResEnv ad id rest false
| id :: rest -> ResolveLongIndentAsModuleOrNamespaceOrStaticClass cenv.g 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
60 changes: 0 additions & 60 deletions tests/fsharp/core/longnames/test.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -688,66 +688,6 @@ 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
39 changes: 39 additions & 0 deletions tests/fsharp/core/longnames/version46/test.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

test.fs(34,17,34,21): typecheck error FS0039: The namespace 'Math' is not defined.

test.fs(35,13,35,16): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following:
min
sin

test.fs(41,17,41,21): typecheck error FS0039: The namespace 'Math' is not defined.

test.fs(42,13,42,16): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following:
min
sin

test.fs(44,17,44,21): typecheck error FS0039: The namespace 'Math' is not defined.

test.fs(45,14,45,17): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following:
min
sin

test.fs(51,10,51,16): typecheck error FS0039: The namespace or module 'MyMath' is not defined. Maybe you want one of the following:
Math

test.fs(52,13,52,16): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following:
min
sin

test.fs(53,14,53,17): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following:
min
sin

test.fs(60,13,60,20): typecheck error FS0039: The value or constructor 'AutoMin' is not defined.

test.fs(61,14,61,21): typecheck error FS0039: The value or constructor 'AutoMin' is not defined.

test.fs(67,10,67,24): typecheck error FS0039: The namespace or module 'AutoOpenMyMath' is not defined.

test.fs(70,13,70,20): typecheck error FS0039: The value or constructor 'AutoMin' is not defined.

test.fs(71,14,71,21): typecheck error FS0039: The value or constructor 'AutoMin' is not defined.
Expand Down
Loading