Skip to content

Commit 72cf286

Browse files
Martin5210101
andauthored
Warnings for invalid #nowarn arguments (#17871)
* bringing #nowarn args warnings back * warnings for invalid #nowarn arguments * fix v8 case * formatting * release notes * further v8 fixes * fix duplicate prefix removal and add test for it * another stupid error fixed and test added * more fixes, tests * formatting * simplification and fixes. * simplification * removed regex compilation * fixes as proposed in review * avoiding Regex * Using WarningDescription type to get warning number * More descriptive variable names Co-authored-by: Petr Pokorny <[email protected]> * More descriptive variable names - now correct --------- Co-authored-by: Petr Pokorny <[email protected]>
1 parent ae618aa commit 72cf286

File tree

10 files changed

+149
-47
lines changed

10 files changed

+149
-47
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.200.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
* Better ranges for `inherit` error reporting. ([PR #17879](https://github.com/dotnet/fsharp/pull/17879))
2929
* Better ranges for `inherit` `struct` error reporting. ([PR #17886](https://github.com/dotnet/fsharp/pull/17886))
3030
* Better ranges for `inherit` objects error reporting. ([PR #17893](https://github.com/dotnet/fsharp/pull/17893))
31+
* Better ranges for #nowarn error reporting; bring back #nowarn warnings for --langVersion:80; add warnings under feature flag ([PR #17871](https://github.com/dotnet/fsharp/pull/17871))
3132

3233
### Breaking Changes

src/Compiler/Driver/CompilerConfig.fs

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ open FSharp.Compiler.DiagnosticsLogger
2222
open FSharp.Compiler.Features
2323
open FSharp.Compiler.IO
2424
open FSharp.Compiler.CodeAnalysis
25+
open FSharp.Compiler.Syntax
2526
open FSharp.Compiler.Text
2627
open FSharp.Compiler.Text.Range
2728
open FSharp.Compiler.Xml
@@ -91,24 +92,61 @@ let ResolveFileUsingPaths (paths, m, fileName) =
9192
let searchMessage = String.concat "\n " paths
9293
raise (FileNameNotResolved(fileName, searchMessage, m))
9394

94-
let GetWarningNumber (m, warningNumber: string, prefixSupported) =
95-
try
96-
let warningNumber =
97-
if warningNumber.StartsWithOrdinal "FS" then
98-
if prefixSupported then
99-
warningNumber.Substring 2
100-
else
101-
raise (new ArgumentException())
102-
else
103-
warningNumber
95+
[<RequireQualifiedAccess>]
96+
type WarningNumberSource =
97+
| CommandLineOption
98+
| CompilerDirective
99+
100+
[<RequireQualifiedAccess>]
101+
type WarningDescription =
102+
| Int32 of int
103+
| String of string
104+
| Ident of Ident
105+
106+
let GetWarningNumber (m, description: WarningDescription, langVersion: LanguageVersion, source: WarningNumberSource) =
107+
let argFeature = LanguageFeature.ParsedHashDirectiveArgumentNonQuotes
108+
109+
let parse (numStr: string) =
110+
let trimPrefix (s: string) =
111+
if s.StartsWithOrdinal "FS" then s[2..] else s
112+
113+
let tryParseIntWithFailAction (s: string) (failAction: unit -> unit) =
114+
match Int32.TryParse s with
115+
| true, n -> Some n
116+
| false, _ ->
117+
failAction ()
118+
None
119+
120+
let warnInvalid () =
121+
warning (Error(FSComp.SR.buildInvalidWarningNumber numStr, m))
122+
123+
if source = WarningNumberSource.CommandLineOption then
124+
tryParseIntWithFailAction (trimPrefix numStr) id
125+
elif langVersion.SupportsFeature(argFeature) then
126+
tryParseIntWithFailAction (trimPrefix numStr) warnInvalid
127+
else
128+
tryParseIntWithFailAction numStr id
104129

105-
if Char.IsDigit(warningNumber[0]) then
106-
Some(int32 warningNumber)
130+
match description with
131+
| WarningDescription.Int32 n ->
132+
if tryCheckLanguageFeatureAndRecover langVersion argFeature m then
133+
Some n
134+
else
135+
None
136+
| WarningDescription.String s ->
137+
if
138+
source = WarningNumberSource.CompilerDirective
139+
&& not (langVersion.SupportsFeature argFeature)
140+
&& s.StartsWithOrdinal "FS"
141+
then
142+
warning (Error(FSComp.SR.buildInvalidWarningNumber s, m))
143+
144+
parse s
145+
| WarningDescription.Ident ident ->
146+
if tryCheckLanguageFeatureAndRecover langVersion argFeature m then
147+
parse ident.idText
107148
else
108149
None
109-
with _ ->
110-
warning (Error(FSComp.SR.buildInvalidWarningNumber warningNumber, m))
111-
None
112150

113151
let ComputeMakePathAbsolute implicitIncludeDir (path: string) =
114152
try
@@ -934,7 +972,7 @@ type TcConfigBuilder =
934972
member tcConfigB.TurnWarningOff(m, s: string) =
935973
use _ = UseBuildPhase BuildPhase.Parameter
936974

937-
match GetWarningNumber(m, s, tcConfigB.langVersion.SupportsFeature(LanguageFeature.ParsedHashDirectiveArgumentNonQuotes)) with
975+
match GetWarningNumber(m, WarningDescription.String s, tcConfigB.langVersion, WarningNumberSource.CommandLineOption) with
938976
| None -> ()
939977
| Some n ->
940978
// nowarn:62 turns on mlCompatibility, e.g. shows ML compat items in intellisense menus
@@ -949,7 +987,7 @@ type TcConfigBuilder =
949987
member tcConfigB.TurnWarningOn(m, s: string) =
950988
use _ = UseBuildPhase BuildPhase.Parameter
951989

952-
match GetWarningNumber(m, s, tcConfigB.langVersion.SupportsFeature(LanguageFeature.ParsedHashDirectiveArgumentNonQuotes)) with
990+
match GetWarningNumber(m, WarningDescription.String s, tcConfigB.langVersion, WarningNumberSource.CommandLineOption) with
953991
| None -> ()
954992
| Some n ->
955993
// warnon 62 turns on mlCompatibility, e.g. shows ML compat items in intellisense menus

src/Compiler/Driver/CompilerConfig.fsi

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ open FSharp.Compiler.Diagnostics
1717
open FSharp.Compiler.DiagnosticsLogger
1818
open FSharp.Compiler.Features
1919
open FSharp.Compiler.CodeAnalysis
20+
open FSharp.Compiler.Syntax
2021
open FSharp.Compiler.Text
2122
open FSharp.Compiler.BuildGraph
2223

@@ -926,7 +927,20 @@ val TryResolveFileUsingPaths: paths: string seq * m: range * fileName: string ->
926927

927928
val ResolveFileUsingPaths: paths: string seq * m: range * fileName: string -> string
928929

929-
val GetWarningNumber: m: range * warningNumber: string * prefixSupported: bool -> int option
930+
[<RequireQualifiedAccess>]
931+
type WarningNumberSource =
932+
| CommandLineOption
933+
| CompilerDirective
934+
935+
[<RequireQualifiedAccess>]
936+
type WarningDescription =
937+
| Int32 of int
938+
| String of string
939+
| Ident of Ident
940+
941+
val GetWarningNumber:
942+
m: range * description: WarningDescription * langVersion: LanguageVersion * source: WarningNumberSource ->
943+
int option
930944

931945
/// Get the name used for FSharp.Core
932946
val GetFSharpCoreLibraryName: unit -> string

src/Compiler/Driver/CompilerOptions.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,15 +832,15 @@ let errorsAndWarningsFlags (tcConfigB: TcConfigBuilder) =
832832
CompilerOption(
833833
"nowarn",
834834
tagWarnList,
835-
OptionStringList(fun n -> tcConfigB.TurnWarningOff(rangeCmdArgs, trimFS n)),
835+
OptionStringList(fun n -> tcConfigB.TurnWarningOff(rangeCmdArgs, n)),
836836
None,
837837
Some(FSComp.SR.optsNowarn ())
838838
)
839839

840840
CompilerOption(
841841
"warnon",
842842
tagWarnList,
843-
OptionStringList(fun n -> tcConfigB.TurnWarningOn(rangeCmdArgs, trimFS n)),
843+
OptionStringList(fun n -> tcConfigB.TurnWarningOn(rangeCmdArgs, n)),
844844
None,
845845
Some(FSComp.SR.optsWarnOn ())
846846
)

src/Compiler/Driver/ParseAndCheckInputs.fs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -217,25 +217,23 @@ let PostParseModuleSpec (_i, defaultNamespace, isLastCompiland, fileName, intf)
217217
SynModuleOrNamespaceSig(lid, isRecursive, kind, decls, xmlDoc, attributes, None, range, trivia)
218218

219219
let GetScopedPragmasForHashDirective hd (langVersion: LanguageVersion) =
220-
let supportsNonStringArguments =
221-
langVersion.SupportsFeature(LanguageFeature.ParsedHashDirectiveArgumentNonQuotes)
222-
223220
[
224221
match hd with
225-
| ParsedHashDirective("nowarn", numbers, m) ->
226-
for s in numbers do
227-
let warningNumber =
228-
match supportsNonStringArguments, s with
229-
| _, ParsedHashDirectiveArgument.SourceIdentifier _ -> None
230-
| true, ParsedHashDirectiveArgument.LongIdent _ -> None
231-
| true, ParsedHashDirectiveArgument.Int32(n, _) -> GetWarningNumber(m, string n, true)
232-
| true, ParsedHashDirectiveArgument.Ident(s, _) -> GetWarningNumber(m, s.idText, true)
233-
| _, ParsedHashDirectiveArgument.String(s, _, _) -> GetWarningNumber(m, s, true)
222+
| ParsedHashDirective("nowarn", args, _) ->
223+
for arg in args do
224+
let rangeAndDescription =
225+
match arg with
226+
| ParsedHashDirectiveArgument.Int32(n, m) -> Some(m, WarningDescription.Int32 n)
227+
| ParsedHashDirectiveArgument.Ident(ident, m) -> Some(m, WarningDescription.Ident ident)
228+
| ParsedHashDirectiveArgument.String(s, _, m) -> Some(m, WarningDescription.String s)
234229
| _ -> None
235230

236-
match warningNumber with
231+
match rangeAndDescription with
237232
| None -> ()
238-
| Some n -> ScopedPragma.WarningOff(m, n)
233+
| Some(m, description) ->
234+
match GetWarningNumber(m, description, langVersion, WarningNumberSource.CompilerDirective) with
235+
| None -> ()
236+
| Some n -> ScopedPragma.WarningOff(m, n)
239237
| _ -> ()
240238
]
241239

@@ -912,7 +910,8 @@ let ProcessMetaCommandsFromInput
912910
state
913911

914912
| ParsedHashDirective("nowarn", hashArguments, m) ->
915-
let arguments = parsedHashDirectiveArguments hashArguments tcConfig.langVersion
913+
let arguments = parsedHashDirectiveArgumentsNoCheck hashArguments
914+
916915
List.fold (fun state d -> nowarnF state (m, d)) state arguments
917916

918917
| ParsedHashDirective(("reference" | "r") as c, [], m) ->

src/Compiler/Interactive/fsi.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3839,7 +3839,8 @@ type FsiInteractionProcessor
38393839
istate, Completed None
38403840

38413841
| ParsedHashDirective("nowarn", nowarnArguments, m) ->
3842-
let numbers = (parsedHashDirectiveArguments nowarnArguments tcConfigB.langVersion)
3842+
let numbers = (parsedHashDirectiveArgumentsNoCheck nowarnArguments)
3843+
38433844
List.iter (fun (d: string) -> tcConfigB.TurnWarningOff(m, d)) numbers
38443845
istate, Completed None
38453846

src/Compiler/SyntaxTree/SyntaxTreeOps.fs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,16 @@ let parsedHashDirectiveArguments (input: ParsedHashDirectiveArgument list) (lang
10051005
| false -> None)
10061006
input
10071007

1008+
let parsedHashDirectiveArgumentsNoCheck (input: ParsedHashDirectiveArgument list) =
1009+
List.map
1010+
(function
1011+
| ParsedHashDirectiveArgument.String(s, _, _) -> s
1012+
| ParsedHashDirectiveArgument.SourceIdentifier(_, v, _) -> v
1013+
| ParsedHashDirectiveArgument.Int32(n, m) -> string n
1014+
| ParsedHashDirectiveArgument.Ident(ident, m) -> ident.idText
1015+
| ParsedHashDirectiveArgument.LongIdent(ident, m) -> longIdentToString ident)
1016+
input
1017+
10081018
let parsedHashDirectiveStringArguments (input: ParsedHashDirectiveArgument list) (_langVersion: LanguageVersion) =
10091019
List.choose
10101020
(function

src/Compiler/SyntaxTree/SyntaxTreeOps.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ val synExprContainsError: inpExpr: SynExpr -> bool
322322

323323
val parsedHashDirectiveArguments: ParsedHashDirectiveArgument list -> LanguageVersion -> string list
324324

325+
val parsedHashDirectiveArgumentsNoCheck: ParsedHashDirectiveArgument list -> string list
326+
325327
val parsedHashDirectiveStringArguments: ParsedHashDirectiveArgument list -> LanguageVersion -> string list
326328

327329
/// 'e1 && e2'

tests/FSharp.Compiler.ComponentTests/CompilerDirectives/NonStringArgs.fs

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@ module NonStringArgs =
2424
|> asExe
2525
|> compile
2626
|> shouldFail
27-
|> withDiagnostics[
27+
|> withDiagnostics [
2828
if languageVersion = "8.0" then
29-
(Warning 203, Line 6, Col 1, Line 6, Col 13, "Invalid warning number 'FS'")
3029
(Error 3350, Line 3, Col 9, Line 3, Col 11, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
3130
(Error 3350, Line 4, Col 9, Line 4, Col 15, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
3231
(Error 3350, Line 5, Col 9, Line 5, Col 13, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
32+
(Warning 203, Line 6, Col 9, Line 6, Col 13, "Invalid warning number 'FS'");
33+
(Warning 203, Line 7, Col 9, Line 7, Col 17, "Invalid warning number 'FSBLAH'");
3334
else
34-
(Warning 203, Line 3, Col 1, Line 3, Col 11, "Invalid warning number 'FS'")
35-
(Warning 203, Line 6, Col 1, Line 6, Col 13, "Invalid warning number 'FS'")
35+
(Warning 203, Line 3, Col 9, Line 3, Col 11, "Invalid warning number 'FS'");
36+
(Warning 203, Line 4, Col 9, Line 4, Col 15, "Invalid warning number 'FSBLAH'");
37+
(Warning 203, Line 5, Col 9, Line 5, Col 13, "Invalid warning number 'ACME'");
38+
(Warning 203, Line 6, Col 9, Line 6, Col 13, "Invalid warning number 'FS'");
39+
(Warning 203, Line 7, Col 9, Line 7, Col 17, "Invalid warning number 'FSBLAH'");
40+
(Warning 203, Line 8, Col 9, Line 8, Col 15, "Invalid warning number 'ACME'")
3641
]
3742

3843

@@ -55,14 +60,20 @@ module NonStringArgs =
5560
|> asExe
5661
|> compile
5762
|> shouldFail
58-
|> withDiagnostics[
63+
|> withDiagnostics [
5964
if languageVersion = "8.0" then
60-
(Warning 203, Line 2, Col 1, Line 9, Col 11, "Invalid warning number 'FS'")
6165
(Error 3350, Line 4, Col 5, Line 4, Col 7, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
6266
(Error 3350, Line 5, Col 5, Line 5, Col 11, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
6367
(Error 3350, Line 6, Col 5, Line 6, Col 9, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
68+
(Warning 203, Line 7, Col 5, Line 7, Col 9, "Invalid warning number 'FS'");
69+
(Warning 203, Line 8, Col 5, Line 8, Col 13, "Invalid warning number 'FSBLAH'");
6470
else
65-
(Warning 203, Line 2, Col 1, Line 9, Col 11, "Invalid warning number 'FS'")
71+
(Warning 203, Line 4, Col 5, Line 4, Col 7, "Invalid warning number 'FS'");
72+
(Warning 203, Line 5, Col 5, Line 5, Col 11, "Invalid warning number 'FSBLAH'");
73+
(Warning 203, Line 6, Col 5, Line 6, Col 9, "Invalid warning number 'ACME'");
74+
(Warning 203, Line 7, Col 5, Line 7, Col 9, "Invalid warning number 'FS'");
75+
(Warning 203, Line 8, Col 5, Line 8, Col 13, "Invalid warning number 'FSBLAH'");
76+
(Warning 203, Line 9, Col 5, Line 9, Col 11, "Invalid warning number 'ACME'")
6677
]
6778

6879

@@ -81,12 +92,18 @@ module NonStringArgs =
8192
|> shouldFail
8293
|> withDiagnostics [
8394
if languageVersion = "8.0" then
84-
(Warning 203, Line 3, Col 1, Line 3, Col 44, "Invalid warning number 'FS'")
8595
(Error 3350, Line 3, Col 9, Line 3, Col 11, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
8696
(Error 3350, Line 3, Col 12, Line 3, Col 18, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
8797
(Error 3350, Line 3, Col 19, Line 3, Col 23, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
98+
(Warning 203, Line 3, Col 24, Line 3, Col 28, "Invalid warning number 'FS'");
99+
(Warning 203, Line 3, Col 29, Line 3, Col 37, "Invalid warning number 'FSBLAH'");
88100
else
89-
(Warning 203, Line 3, Col 1, Line 3, Col 44, "Invalid warning number 'FS'")
101+
(Warning 203, Line 3, Col 9, Line 3, Col 11, "Invalid warning number 'FS'");
102+
(Warning 203, Line 3, Col 12, Line 3, Col 18, "Invalid warning number 'FSBLAH'");
103+
(Warning 203, Line 3, Col 19, Line 3, Col 23, "Invalid warning number 'ACME'");
104+
(Warning 203, Line 3, Col 24, Line 3, Col 28, "Invalid warning number 'FS'");
105+
(Warning 203, Line 3, Col 29, Line 3, Col 37, "Invalid warning number 'FSBLAH'");
106+
(Warning 203, Line 3, Col 38, Line 3, Col 44, "Invalid warning number 'ACME'")
90107
]
91108

92109

@@ -128,12 +145,32 @@ module DoBinding =
128145
(Warning 1104, Line 5, Col 15, Line 5, Col 31, "Identifiers containing '@' are reserved for use in F# code generation")
129146
(Error 3350, Line 2, Col 9, Line 2, Col 11, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
130147
(Error 3350, Line 2, Col 12, Line 2, Col 18, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
148+
(Warning 203, Line 2, Col 26, Line 2, Col 34, "Invalid warning number 'FS3221'")
131149
]
132150
else
133151
compileResult
134152
|> shouldSucceed
135153

136154

155+
[<InlineData("8.0")>]
156+
[<InlineData("9.0")>]
157+
[<Theory>]
158+
let ``#nowarn - errors - compiler options`` (languageVersion) =
159+
160+
FSharp """
161+
match None with None -> () // creates FS0025 - ignored due to flag
162+
"" // creates FS0020 - ignored due to flag
163+
""" // creates FS0988 - not ignored, different flag prefix
164+
|> withLangVersion languageVersion
165+
|> withOptions ["--nowarn:NU0988"; "--nowarn:FS25"; "--nowarn:20"; "--nowarn:FS"; "--nowarn:FSBLAH"]
166+
|> asExe
167+
|> compile
168+
|> shouldFail
169+
|> withDiagnostics [
170+
(Warning 988, Line 3, Col 3, Line 3, Col 3, "Main module of program is empty: nothing will happen when it is run")
171+
]
172+
173+
137174
[<InlineData("8.0")>]
138175
[<InlineData("9.0")>]
139176
[<Theory>]
@@ -248,7 +285,7 @@ printfn "Hello, World"
248285
|> asExe
249286
|> compile
250287
|> shouldFail
251-
|> withDiagnostics[
288+
|> withDiagnostics [
252289
(Error 76, Line 2, Col 9, Line 2, Col 11, "This directive may only be used in F# script files (extensions .fsx or .fsscript). Either remove the directive, move this code to a script file or delimit the directive with '#if INTERACTIVE'/'#endif'.")
253290
(Error 76, Line 3, Col 9, Line 3, Col 14, "This directive may only be used in F# script files (extensions .fsx or .fsscript). Either remove the directive, move this code to a script file or delimit the directive with '#if INTERACTIVE'/'#endif'.")
254291
(Error 76, Line 4, Col 9, Line 4, Col 17, "This directive may only be used in F# script files (extensions .fsx or .fsscript). Either remove the directive, move this code to a script file or delimit the directive with '#if INTERACTIVE'/'#endif'.")

tests/service/data/SyntaxTree/ParsedHashDirective/TripleQuoteStringAsParsedHashDirectiveArgument.fs.bsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ ImplFile
22
(ParsedImplFileInput
33
("/root/ParsedHashDirective/TripleQuoteStringAsParsedHashDirectiveArgument.fs",
44
false, QualifiedNameOfFile TripleQuoteStringAsParsedHashDirectiveArgument,
5-
[WarningOff ((2,0--2,16), 40)], [],
5+
[WarningOff ((2,8--2,16), 40)], [],
66
[SynModuleOrNamespace
77
([TripleQuoteStringAsParsedHashDirectiveArgument], false, AnonModule,
88
[HashDirective

0 commit comments

Comments
 (0)