Skip to content

Commit 2d52cb9

Browse files
committed
add tests for some nullability scenarios, and make tests easier to read in test result view
1 parent 091727c commit 2d52cb9

File tree

2 files changed

+68
-36
lines changed

2 files changed

+68
-36
lines changed

test/FsAutoComplete.Tests.Lsp/CoreTests.fs

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ let tooltipTests state =
392392
}
393393
|> Async.Cache
394394

395-
let verifySignature line character expectedSignature =
395+
let verifySignature name line character expectedSignature =
396396
testCaseAsync
397-
(sprintf "tooltip for line %d character %d should be '%s'" line character expectedSignature)
397+
name
398398
(async {
399399
let! server, scriptPath = server
400400

@@ -411,11 +411,11 @@ let tooltipTests state =
411411

412412
let concatLines = String.concat Environment.NewLine
413413

414-
let verifyDescriptionImpl testCaseAsync line character expectedDescription =
414+
let verifyDescriptionImpl testCaseAsync name line character expectedDescription =
415415
let expectedDescription = concatLines expectedDescription
416416

417417
testCaseAsync
418-
(sprintf "description for line %d character %d" line character)
418+
(sprintf name)
419419
(async {
420420
let! server, scriptPath = server
421421

@@ -430,28 +430,28 @@ let tooltipTests state =
430430
| Result.Error errors -> failtestf "Error while getting description: %A" errors
431431
})
432432

433-
let verifyDescription line character expectedDescription =
434-
verifyDescriptionImpl testCaseAsync line character expectedDescription
433+
let verifyDescription name line character expectedDescription =
434+
verifyDescriptionImpl testCaseAsync name line character expectedDescription
435435

436436
testSequenced
437437
<| testList
438438
"tooltip evaluation"
439-
[ testList
439+
[ ftestList
440440
"tests"
441-
[ verifyDescription
441+
[ verifyDescription "language keywords"
442442
0u
443443
2u
444444
[ "**Description**"
445445
""
446446
""
447447
"Used to associate, or bind, a name to a value or function."
448448
"" ] // `let` keyword
449-
verifySignature 0u 4u "val arrayOfTuples: (int * int) array" // verify that even the first letter of the tooltip triggers correctly
450-
verifySignature 0u 5u "val arrayOfTuples: (int * int) array" // inner positions trigger
451-
verifySignature 1u 5u "val listOfTuples: list<int * int>" // verify we default to prefix-generics style
452-
verifySignature 2u 5u "val listOfStructTuples: list<struct (int * int)>" // verify we render struct tuples in a round-tripabble format
453-
verifySignature 3u 5u "val floatThatShouldHaveGenericReportedInTooltip: float" // verify we strip <MeasureOne> measure annotations
454-
verifyDescription
449+
verifySignature "trigger.firstCharacter" 0u 4u "val arrayOfTuples: (int * int) array" // verify that even the first letter of the tooltip triggers correctly
450+
verifySignature "trigger.innerCharacter" 0u 5u "val arrayOfTuples: (int * int) array" // inner positions trigger
451+
verifySignature "uses prefix generics" 1u 5u "val listOfTuples: list<int * int>" // verify we default to prefix-generics style
452+
verifySignature "struct tuple handling" 2u 5u "val listOfStructTuples: list<struct (int * int)>" // verify we render struct tuples in a round-tripabble format
453+
verifySignature "strip meaningless units of measure" 3u 5u "val floatThatShouldHaveGenericReportedInTooltip: float" // verify we strip <MeasureOne> measure annotations
454+
verifyDescription "tooltip formatting for external library functions"
455455
4u
456456
4u
457457
[ "**Description**"
@@ -469,7 +469,7 @@ let tooltipTests state =
469469
"**Generic Parameters**"
470470
""
471471
"* `'T` is `System.String`" ] // verify fancy descriptions for external library functions and correct backticks for multiple segments
472-
verifyDescription
472+
verifyDescription "multiple generic parameters are explained"
473473
13u
474474
11u
475475
[ "**Description**"
@@ -487,38 +487,38 @@ let tooltipTests state =
487487
"**Returns**"
488488
""
489489
"" ]
490-
verifySignature 14u 5u "val nestedTuples: int * ((int * int) * int)" // verify that tuples render correctly (parens, etc)
491-
verifySignature 15u 5u "val nestedStructTuples: int * struct (int * int)" // verify we can differentiate between struct and non-struct tuples
492-
verifySignature 21u 9u "val speed: float<m/s>" // verify we nicely-render measure annotations
490+
verifySignature "nested tuples" 14u 5u "val nestedTuples: int * ((int * int) * int)" // verify that tuples render correctly (parens, etc)
491+
verifySignature "mixed struct and reference tuples" 15u 5u "val nestedStructTuples: int * struct (int * int)" // verify we can differentiate between struct and non-struct tuples
492+
verifySignature "units of measure are rendered nicely" 21u 9u "val speed: float<m/s>" // verify we nicely-render measure annotations
493493
// verify formatting of function-parameters to values. NOTE: we want to wrap them in parens for user clarity eventually.
494-
verifySignature
494+
verifySignature "parameters that are functions are wrapped in parens for clarity"
495495
26u
496496
5u
497497
(concatLines [ "val funcWithFunParam:"; " f: (int -> unit) ->"; " i: int"; " -> unit" ])
498498
// verify formatting of tuple args. NOTE: we want to wrap tuples in parens for user clarify eventually.
499-
verifySignature
499+
verifySignature "tuple args are split on each line"
500500
30u
501501
12u
502502
(concatLines [ "val funcWithTupleParam:"; " int *"; " int"; " -> int * int" ])
503503
// verify formatting of struct tuple args in parameter tooltips.
504-
verifySignature
504+
verifySignature "struct tuple parameters are rendered correctly"
505505
32u
506506
12u
507507
(concatLines
508508
[ "val funcWithStructTupleParam:"
509509
" f: struct (int * int)"
510510
" -> struct (int * int)" ])
511-
verifySignature 36u 15u (concatLines [ "member Foo:"; " stuff: int * int * int"; " -> int" ])
512-
verifySignature
511+
verifySignature "tuple member parameters are gathered on single line" 36u 15u (concatLines [ "member Foo:"; " stuff: int * int * int"; " -> int" ])
512+
verifySignature "multiple named member parameters are split on each line"
513513
37u
514514
15u
515515
(concatLines [ "member Bar:"; " a: int *"; " b: int *"; " c: int"; " -> int" ])
516516
// verify formatting for multi-char operators
517-
verifySignature 39u 7u (concatLines [ "val ( .>> ):"; " x: int ->"; " y: int"; " -> int" ])
517+
verifySignature "multi-char operator rendering" 39u 7u (concatLines [ "val ( .>> ):"; " x: int ->"; " y: int"; " -> int" ])
518518
// verify formatting for single-char operators
519-
verifySignature 41u 6u (concatLines [ "val ( ^ ):"; " x: int ->"; " y: int"; " -> int" ])
519+
verifySignature "single-char operator rendering" 41u 6u (concatLines [ "val ( ^ ):"; " x: int ->"; " y: int"; " -> int" ])
520520
// verify rendering of generic constraints
521-
verifySignature
521+
verifySignature "generic constraints on parameters"
522522
43u
523523
13u
524524
(concatLines
@@ -527,24 +527,24 @@ let tooltipTests state =
527527
" y: 'b (requires static member ( + ) )"
528528
" -> 'c" ])
529529
//verify rendering of solved generic constraints in tooltips for members where they are solved
530-
verifyDescription
530+
verifyDescription "solved generic parameters are called out in tooltip"
531531
45u
532532
15u
533533
[ "**Generic Parameters**"
534534
""
535535
"* `'a` is `int`"
536536
"* `'b` is `int`"
537537
"* `'c` is `int`" ]
538-
verifySignature
538+
verifySignature "optional member parameters are rendered with leading question mark"
539539
48u
540540
28u
541541
(concatLines
542542
[ "static member Start:"
543543
" body : (MailboxProcessor<string> -> Async<unit>) *"
544544
" ?cancellationToken: System.Threading.CancellationToken"
545545
" -> MailboxProcessor<string>" ])
546-
verifySignature 54u 9u "Case2 of string * newlineBefore: bool * newlineAfter: bool"
547-
verifySignature
546+
verifySignature "union case named parameters are rendered" 54u 9u "Case2 of string * newlineBefore: bool * newlineAfter: bool"
547+
verifySignature "active pattern signatures with potentially-nullable results"
548548
60u
549549
7u
550550
(concatLines
@@ -557,30 +557,30 @@ let tooltipTests state =
557557
" input: Expr"
558558
" -> option<objnull * System.Type>" ])
559559
#endif
560-
verifySignature
560+
verifySignature "generic constraint rendering for IWSAM"
561561
77u
562562
5u
563563
(concatLines [
564564
"val testIWSAMTest:"
565565
" unit"
566566
" -> Result<string,'e> (requires :> IWSAMTest<'e>)"
567567
])
568-
verifySignature
568+
verifySignature "multiple generic constraints for IWASMs"
569569
90u
570570
25u
571571
(concatLines [
572572
"static member GetAwaiter:"
573573
" awaitable: 'Awaitable (requires member GetAwaiter )"
574574
" -> Awaiter<^Awaiter,'TResult> (requires :> ICriticalNotifyCompletion and member IsCompleted and member GetResult)"
575575
])
576-
verifySignature
576+
verifySignature "basic active pattern"
577577
65u
578578
7u
579579
(concatLines
580580
[ "active pattern DefaultValue: "
581581
" input: Expr"
582582
" -> option<System.Type>" ])
583-
verifySignature
583+
verifySignature "basic active pattern with nullability awareness"
584584
70u
585585
7u
586586
(concatLines
@@ -593,13 +593,39 @@ let tooltipTests state =
593593
" input: Expr"
594594
" -> option<objnull * System.Type * string>" ])
595595
#endif
596-
verifySignature
596+
verifySignature "interface with members with and without parameter names"
597597
96u
598598
7u
599599
(concatLines
600600
[ "interface IWithAndWithoutParamNames"
601601
" abstract member WithParamNames: arg1: int * arg2: float -> string"
602-
" abstract member WithoutParamNames: int * string -> int" ]) ] ]
602+
" abstract member WithoutParamNames: int * string -> int" ])
603+
verifySignature "function with unsolved nullable parameter" 100u 7u (concatLines [
604+
"val usesNullable:"
605+
" x: 't | null"
606+
" -> 't (requires reference )"
607+
])
608+
609+
verifySignature "function with concrete nullable parameter" 101u 7u (concatLines [
610+
"val usesConcreteNullable:"
611+
" x: string | null"
612+
" -> String (requires reference )"
613+
])
614+
verifySignature "function with generic nullable return" 102u 7u (concatLines [
615+
"val makesNullable:"
616+
" x: 'x (requires reference)"
617+
" -> 'x | null"
618+
])
619+
verifySignature "function with concrete nullable return" 103u 7u (concatLines [
620+
"val makesConcreteNullable:"
621+
" x: string"
622+
" -> string | null"
623+
])
624+
verifySignature "function with nullable return from BCL call" 104u 7u (concatLines [
625+
"val usesBCLNullable:"
626+
" key: string"
627+
" -> string | null"
628+
])] ]
603629

604630
let closeTests state =
605631
// Note: clear diagnostics also implies clear caches (-> remove file & project options from State).

test/FsAutoComplete.Tests.Lsp/TestCases/Tooltips/Script.fsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,9 @@ type Awaitable =
9797
type IWithAndWithoutParamNames =
9898
abstract member WithParamNames : arg1: int * arg2: float -> string
9999
abstract member WithoutParamNames : int * string -> int
100+
101+
let usesNullable (x: 't | null) = nonNull x
102+
let usesConcreteNullable (x: string | null) = nonNull x
103+
let makesNullable (x: 'x): 'x | null = null
104+
let makesConcreteNullable (x: string): string | null = null
105+
let usesBCLNullable (key: string) = System.Environment.GetEnvironmentVariable(key)

0 commit comments

Comments
 (0)