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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/Compiler/Checking/PostInferenceChecks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,24 @@ let BindVal cenv env (v: Val) =
//printfn "binding %s..." v.DisplayName
let alreadyDone = cenv.boundVals.ContainsKey v.Stamp
cenv.boundVals[v.Stamp] <- 1

let topLevelBindingHiddenBySignatureFile () =
let parentHasSignatureFile () =
match v.TryDeclaringEntity with
| ParentNone -> false
| Parent p ->
match p.TryDeref with
| ValueNone -> false
| ValueSome e -> e.HasSignatureFile

v.IsModuleBinding && not v.HasSignatureFile && parentHasSignatureFile ()

if not env.external &&
not alreadyDone &&
cenv.reportErrors &&
not v.HasBeenReferenced &&
not v.IsCompiledAsTopLevel &&
not (v.DisplayName.StartsWithOrdinal("_")) &&
(not v.IsCompiledAsTopLevel || topLevelBindingHiddenBySignatureFile ()) &&
not (v.DisplayName.StartsWithOrdinal("_")) &&
not v.IsCompilerGenerated then

if v.IsCtorThisVal then
Expand Down
4 changes: 1 addition & 3 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,7 @@ type FSharpSymbolUse(denv: DisplayEnv, symbol: FSharpSymbol, inst: TyparInstanti

let fileHasSignatureFile = fileSignatureLocation <> fileDeclarationLocation

let symbolIsNotInSignatureFile = m.SignatureLocation = Some m.DeclarationLocation

fileHasSignatureFile && symbolIsNotInSignatureFile
fileHasSignatureFile && not m.HasSignatureFile
|| not m.IsModuleValueOrMember
|| m.Accessibility.IsPrivate
| :? FSharpEntity as m -> m.Accessibility.IsPrivate
Expand Down
8 changes: 8 additions & 0 deletions src/Compiler/Symbols/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,14 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
| P _ -> true
| _ -> false

member x.HasSignatureFile =
match fsharpInfo() with
| None -> false
| Some vref ->
match vref.TryDeref with
| ValueNone -> false
| ValueSome v -> v.HasSignatureFile

member _.IsEvent =
match d with
| E _ -> true
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Symbols/Symbols.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,9 @@ type FSharpMemberOrFunctionOrValue =
/// Indicates if this is a method member
member IsMethod: bool

/// Indicates if the value has a signature file counterpart
member HasSignatureFile: bool

/// Indicates if this is a property and there exists an associated getter method
member HasGetterMethod: bool

Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/TypedTree/TypedTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,8 @@ type Entity =

/// Indicates if we have pre-determined that a type definition has a self-referential constructor using 'as x'
member x.HasSelfReferentialConstructor = x.entity_flags.HasSelfReferentialConstructor

member x.HasSignatureFile = x.SigRange <> x.DefinitionRange

/// Set the custom attributes on an F# type definition.
member x.SetAttribs attribs = x.entity_attribs <- attribs
Expand Down Expand Up @@ -2803,6 +2805,9 @@ type Val =
// Indicates if this value was declared to be a type function, e.g. "let f<'a> = typeof<'a>"
member x.IsTypeFunction = x.val_flags.IsTypeFunction

member x.HasSignatureFile =
x.SigRange <> x.DefinitionRange

/// Get the inline declaration on the value
member x.InlineInfo = x.val_flags.InlineInfo

Expand Down
6 changes: 6 additions & 0 deletions src/Compiler/TypedTree/TypedTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,9 @@ type Entity =
/// Indicates if we have pre-determined that a type definition has a self-referential constructor using 'as x'
member HasSelfReferentialConstructor: bool

/// Indicates if the value has a signature file counterpart
member HasSignatureFile: bool

/// Get the Abstract IL scope, nesting type metadata for this
/// type definition, assuming it is backed by Abstract IL metadata.
member ILTyconInfo: TILObjectReprData
Expand Down Expand Up @@ -2085,6 +2088,9 @@ type Val =

member IsTypeFunction: bool

/// Indicates if the value has a signature file counterpart
member HasSignatureFile: bool

/// The value of a value or member marked with [<LiteralAttribute>]
member LiteralValue: Const option

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,111 @@ module warnon =
|> withDiagnosticMessageMatches "The value 'n' is unused$"
|> ignore

[<Fact>]
let ``warnon unused public function hidden by signature file`` () =
let signatureFile: SourceCodeFileKind =
SourceCodeFileKind.Create(
"Library.fsi",
"""
module Foo

val add: a:int -> b:int -> int
""" )

let implementationFile =
SourceCodeFileKind.Create(
"Library.fs",
"""
module Foo

let add a b = a + b
let subtract a b = a - b
""" )

fsFromString signatureFile
|> FS
|> withAdditionalSourceFile implementationFile
|> withOptions ["--warnon:FS1182"]
|> asLibrary
|> compile
|> withWarningCode 1182
|> withDiagnosticMessageMatches "The value 'subtract' is unused$"
|> ignore

[<Fact>]
let ``Don't warnon unused public function`` () =
let implementationFile =
SourceCodeFileKind.Create(
"Library.fs",
"""
module Foo

let add a b = a + b
let subtract a b = a - b
""" )

fsFromString implementationFile
|> FS
|> withOptions ["--warnon:FS1182"]
|> asLibrary
|> compile
|> withDiagnostics []
|> ignore

[<Fact>]
let ``Don't warnon unused public function hidden by signature file that starts with an underscore`` () =
let signatureFile: SourceCodeFileKind =
SourceCodeFileKind.Create(
"Library.fsi",
"""
module Foo

val add: a:int -> b:int -> int
""" )

let implementationFile =
SourceCodeFileKind.Create(
"Library.fs",
"""
module Foo

let add a b = a + b
let _subtract a b = a - b
""" )

fsFromString signatureFile
|> FS
|> withAdditionalSourceFile implementationFile
|> withOptions ["--warnon:FS1182"]
|> asLibrary
|> compile
|> withDiagnostics []
|> ignore

[<Fact>]
let ``Type extensions are not included in this warnon check`` () =
let signatureFile: SourceCodeFileKind =
SourceCodeFileKind.Create(
"Library.fsi",
"""
module Foo
""" )

let implementationFile =
SourceCodeFileKind.Create(
"Library.fs",
"""
module Foo

type System.Int32 with
member x.Bar () = x + 1
""" )

fsFromString signatureFile
|> FS
|> withAdditionalSourceFile implementationFile
|> withOptions ["--warnon:FS1182"]
|> asLibrary
|> compile
|> shouldSucceed
|> ignore
Original file line number Diff line number Diff line change
Expand Up @@ -2012,7 +2012,6 @@ FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: FSharp.Compiler.Symbols.
FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String ToString()
FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] DependencyFiles
FSharp.Compiler.CodeAnalysis.FSharpCheckProjectResults: System.String[] get_DependencyFiles()
FSharp.Compiler.CodeAnalysis.FSharpChecker
FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Create(Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.CodeAnalysis.LegacyReferenceResolver], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.String,System.DateTime],Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Object,System.IntPtr,System.Int32]]]], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean])
FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker Instance
FSharp.Compiler.CodeAnalysis.FSharpChecker: FSharp.Compiler.CodeAnalysis.FSharpChecker get_Instance()
Expand Down Expand Up @@ -4782,6 +4781,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean Equals(System.Obj
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean EventIsStandard
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasGetterMethod
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasSetterMethod
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasSignatureFile
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsActivePattern
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsBaseValue
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsCompilerGenerated
Expand Down Expand Up @@ -4814,6 +4814,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsValue
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_EventIsStandard()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasGetterMethod()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasSetterMethod()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasSignatureFile()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsActivePattern()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsBaseValue()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsCompilerGenerated()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4781,6 +4781,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean Equals(System.Obj
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean EventIsStandard
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasGetterMethod
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasSetterMethod
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasSignatureFile
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsActivePattern
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsBaseValue
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsCompilerGenerated
Expand Down Expand Up @@ -4813,6 +4814,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsValue
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_EventIsStandard()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasGetterMethod()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasSetterMethod()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasSignatureFile()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsActivePattern()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsBaseValue()
FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsCompilerGenerated()
Expand Down