diff --git a/tests/FSharp.Compiler.Service.Tests/Checker.fs b/tests/FSharp.Compiler.Service.Tests/Checker.fs index ca583beb25c..c2f280eaa3c 100644 --- a/tests/FSharp.Compiler.Service.Tests/Checker.fs +++ b/tests/FSharp.Compiler.Service.Tests/Checker.fs @@ -2,10 +2,14 @@ namespace FSharp.Compiler.Service.Tests open System open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics open FSharp.Compiler.EditorServices open FSharp.Compiler.Text open FSharp.Compiler.Text.Range open FSharp.Compiler.Tokenization +open FSharp.Test.Assert +open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts +open Xunit type SourceContext = { Source: string @@ -125,6 +129,9 @@ module CheckResultsExtensions = member this.GetTooltip(context: ResolveContext, width) = this.GetToolTip(context.Pos.Line, context.Pos.Column, context.LineText, context.Names, FSharpTokenTag.Identifier, width) + member this.GetDeclarationLocation(context: ResolveContext) = + this.GetDeclarationLocation(context.Pos.Line, context.Pos.Column, context.LineText, context.Names) + member this.GetCodeCompletionSuggestions(context: CodeCompletionContext, parseResults: FSharpParseFileResults, options: FSharpCodeCompletionOptions) = this.GetDeclarationListInfo(Some parseResults, context.Pos.Line, context.LineText, context.PartialIdentifier, options = options) @@ -173,6 +180,11 @@ module Checker = let getCompletionInfo markedSource = getCompletionInfoWithOptions FSharpCodeCompletionOptions.Default markedSource + let getCompletionInfoOfSignatureFile markedSource = + let context = getCompletionContext markedSource + let parseResults, checkResults = getParseAndCheckResultsOfSignatureFile context.Source + checkResults.GetCodeCompletionSuggestions(context, parseResults, FSharpCodeCompletionOptions.Default) + let getSymbolUses (markedSource: string) = let context, checkResults = getCheckedResolveContext markedSource checkResults.GetSymbolUses(context) @@ -184,7 +196,7 @@ module Checker = let getTooltipWithOptions (options: string array) (markedSource: string) = let context = getResolveContext markedSource let _, checkResults = getParseAndCheckResultsWithOptions options context.Source - checkResults.GetToolTip(context.Pos.Line, context.Pos.Column, context.LineText, context.Names, FSharpTokenTag.Identifier) + checkResults.GetTooltip(context) let getTooltip (markedSource: string) = getTooltipWithOptions [||] markedSource @@ -192,3 +204,36 @@ module Checker = let getMethodOverloads names (markedSource: string) = let context, checkResults = getCheckedResolveContext markedSource checkResults.GetMethodOverloads(context, names) + +/// Shared assertion helpers reused by the completion, editor, tooltip and type-checker-recovery +/// test files. Defined here (an early-compiled file) so every consuming file sees a single +/// definition instead of redefining its own copy. +[] +module AssertHelpers = + let assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = + let itemNames = + completionInfo.Items + |> Array.map _.NameInCode + |> Array.map normalizeNewLines + |> set + + for name in names do + let name = normalizeNewLines name + Set.contains name itemNames |> shouldEqual contains + + let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = + assertItemsWithNames true names completionInfo + + let assertHasNoItemsWithNames names (completionInfo: DeclarationListInfo) = + assertItemsWithNames false names completionInfo + + let assertAndExtractTooltip (ToolTipText(items)) = + Assert.Equal(1, items.Length) + match items[0] with + | ToolTipElement.Group [ singleElement ] -> + let toolTipText = + singleElement.MainDescription + |> taggedTextToString + toolTipText, singleElement.XmlDoc, singleElement.Remarks |> Option.map taggedTextToString + | _ -> failwith $"Expected group, got {items[0]}" + diff --git a/tests/FSharp.Compiler.Service.Tests/Common.fs b/tests/FSharp.Compiler.Service.Tests/Common.fs index 7fad5ff15c5..a7ca1d2c4f4 100644 --- a/tests/FSharp.Compiler.Service.Tests/Common.fs +++ b/tests/FSharp.Compiler.Service.Tests/Common.fs @@ -7,6 +7,7 @@ open System.IO open System.Collections.Generic open System.Threading.Tasks open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics open FSharp.Compiler.IO open FSharp.Compiler.Symbols open FSharp.Compiler.Syntax @@ -363,6 +364,12 @@ let getParseResultsOfSignatureFile (source: string) = let getParseAndCheckResults (source: string) = parseAndCheckScript("Test.fsx", source) +/// Reference/#load script tests must not share the checker's filename-keyed script-closure +/// cache: a shared "Test.fsx" lets one test's closure (its resolved/failed #r references and +/// their diagnostics) leak into the next. Give each such test a unique script identity. +let getParseAndCheckResultsUniqueName (source: string) = + parseAndCheckScript(Guid.NewGuid().ToString("N") + ".fsx", source) + let getParseAndCheckResultsWithOptions options source = parseAndCheckScriptWithOptions ("Test.fsx", source, options) @@ -376,15 +383,22 @@ let getParseAndCheckResults80 (source: string) = parseAndCheckScript80("Test.fsx", source) -let inline dumpDiagnostics (results: FSharpCheckFileResults) = +let normalizeDiagnosticMessage (d: FSharpDiagnostic) = + d.Message.Split('\n') + |> Array.map _.Trim() + |> Array.filter (fun s -> s.Length > 0) + |> String.concat " " + +let formatDiagnostic (d: FSharpDiagnostic) = + sprintf "%s: %s" (d.Range.ToString()) (normalizeDiagnosticMessage d) + +let dumpDiagnostics (results: FSharpCheckFileResults) = + results.Diagnostics |> Array.map formatDiagnostic |> List.ofArray + +let dumpDiagnosticsOfSeverity (severity: FSharpDiagnosticSeverity) (results: FSharpCheckFileResults) = results.Diagnostics - |> Array.map (fun e -> - let message = - e.Message.Split('\n') - |> Array.map _.Trim() - |> Array.filter (fun s -> s.Length > 0) - |> String.concat " " - sprintf "%s: %s" (e.Range.ToString()) message) + |> Array.filter (fun d -> d.Severity = severity) + |> Array.map formatDiagnostic |> List.ofArray let inline dumpDiagnosticNumbers (results: FSharpCheckFileResults) = diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs new file mode 100644 index 00000000000..66d7a6ae6b4 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs @@ -0,0 +1,233 @@ +module FSharp.Compiler.Service.Tests.CompletionAccessibilityTests + +open Xunit + +[] +let ``PrivateVisible`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility + +module Module1 = + let private fieldPrivate = 1 + let private MethodPrivate x = + x+1 + type private TypePrivate() = + member this.mem = 1 + let a = (*Marker1*) {caret}""" + + assertHasItemWithNames [ "fieldPrivate"; "MethodPrivate"; "TypePrivate" ] info + +[] +let ``InternalVisible`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility + +module Module1 = + let internal fieldInternal = 1 + let internal MethodInternal x = + x+1 + type internal TypeInternal() = + member this.mem = 1 + let a = (*Marker1*) {caret}""" + + assertHasItemWithNames [ "fieldInternal"; "MethodInternal"; "TypeInternal" ] info + +let private widgetInheritanceSource = + """ +open System +//define the base class +type Widget() = + let mutable state = 0 + member internal x.MethodInternal() = state + member public x.MethodPublic(n) = state <- state + n + member private x.MethodPrivate() = (state <> 0) + [] + val mutable internal fieldInternal:int + [] + val mutable public fieldPublic:int + [] + val mutable private fieldPrivate:int +//define the divided class which inherent "Widget" +type Divided() = + inherit Widget() + member x.myPrint() = + base.{caret} +Console.ReadKey(true)""" + +[] +let ``InheritedClass.BaseClassPrivateMethod.Negative`` () = + let info = Checker.getCompletionInfo widgetInheritanceSource + assertHasNoItemsWithNames [ "MethodPrivate"; "fieldPrivate" ] info + +[] +let ``InheritedClass.BaseClassPublicMethodAndProperty`` () = + let info = Checker.getCompletionInfo widgetInheritanceSource + assertHasItemWithNames [ "MethodPublic"; "fieldPublic" ] info + +[] +let ``Visibility.InternalNestedClass.Negative`` () = + let info = Checker.getCompletionInfo "System.Console.{caret}" + + assertHasNoItemsWithNames [ "ControlCDelegateData" ] info + +[] +let ``Visibility.PrivateIdentifierInDiffModule.Negative`` () = + let info = + Checker.getCompletionInfo + """ +module Module1 = + let private fieldPrivate = 1 + let private MethodPrivate x = + x+1 + type private TypePrivate()= + member this.mem = 1 +module Module2 = + Module1.{caret}""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Visibility.PrivateIdentifierInDiffClass.Negative`` () = + let info = + Checker.getCompletionInfo + """ +open System +module Module1 = + type Type1()= + [] + val mutable private fieldPrivate:int + member private x.MethodPrivate() = 1 + type Type2()= + let M1= + let type1 = new Type1() + type1.{caret}""" + + assertHasNoItemsWithNames [ "fieldPrivate"; "MethodPrivate" ] info + +[] +[] + val mutable private PrivateField:int + static member private PrivateMethod() = 1 + member this.Field1 with get () = this.{caret} + member x.MethodTest() = Type1(*MarkerMethodInType*) + let type1 = new Type1() """, + "PrivateField")>] +[] + val mutable private PrivateField:int + static member private PrivateMethod() = 1 + member this.Field1 with get () = this(*MarkerFieldInType*) + member x.MethodTest() = Type1.{caret} + let type1 = new Type1() """, + "PrivateMethod")>] +let ``Visibility.PrivateMemberInSameClass`` (markedSource: string) (expected: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ expected ] info + +[] +let ``Visibility.InternalMethods.DefInSameAssembly`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility +open System +module Module1 = +type Type1()= + [] + val mutable internal fieldInternal:int + member internal x.MethodInternal (x:int) = x+2 +let type1 = new Type1() +type1.{caret}""" + + assertHasItemWithNames [ "fieldInternal"; "MethodInternal" ] info + +[] +[] +[] +let ``ObjInstance.InheritedClass.MethodsWithDiffAccessibility`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "baseField"; "derivedField" ] info + assertHasNoItemsWithNames [ "baseFieldPrivate"; "derivedFieldPrivate" ] info + +[] +[] +[] +let ``Visibility.InheritedClass.MethodsWithDiffAccessibility`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "baseField"; "derivedField"; "derivedFieldPrivate" ] info + assertHasNoItemsWithNames [ "baseFieldPrivate" ] info + +[] +let ``Visibility.InheritedClass.MethodsWithSameNameMethod`` () = + let info = + Checker.getCompletionInfo + """type MyClass = + val foo : int + new (foo) = { foo = foo } +type MyClass2 = + inherit MyClass + val foo : int + new (foo) = { + inherit MyClass(foo) + foo = foo + } +let x = new MyClass2(0) +(*marker*)x.{caret}foo""" + + assertHasItemWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs new file mode 100644 index 00000000000..73bb17aa242 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs @@ -0,0 +1,229 @@ +module FSharp.Compiler.Service.Tests.CompletionAttributesTests + +open Xunit + +[] +[] +[] +[] +[] +[] +[] +[] +let ``Attribute.WhenAttachedTo.Bug70080`` (noneTargetSource: string) = + for prefix in [ ""; "type:"; "module:" ] do + noneTargetSource.Replace("[ Checker.getCompletionInfo + |> assertHasItemWithNames [ "AttributeUsage" ] + +[] +let ``ObsoleteAndOCamlCompatDontAppear`` () = + let info = + Checker.getCompletionInfo + """open System +type X = + static member private Private() = () + [] + static member Obsolete() = () + [] + static member CompilerMessageTest() = () +X.{caret}""" + + assertHasNoItemsWithNames [ "Obsolete"; "CompilerMessageTest" ] info + +[] +let ``Attributes.CanSeeOpenNamespaces.Bug268290.Case1`` () = + let info = + Checker.getCompletionInfo + """ + module Foo + open System + [<{caret} + """ + + assertHasItemWithNames [ "AttributeUsage" ] info + +[] +let ``LongIdent.AsAttribute`` () = + let info = + Checker.getCompletionInfo + """ + [] + type TestAttribute() = + member x.print() = "print" """ + + assertHasItemWithNames [ "ObsoleteAttribute" ] info + +[] +let ``NotShowAttribute`` () = + let info1 = + Checker.getCompletionInfo + """ + open System + [] + type testclass() = + member x.Name() = "test" + [] + type testattribute() = + member x.Empty = 0 + """ + + Assert.Equal(0, info1.Items.Length) + + let info2 = + Checker.getCompletionInfo + """ + open System + [] + type testclass() = + member x.Name() = "test" + [] + type testattribute() = + member x.Empty = 0 + """ + + Assert.Equal(0, info2.Items.Length) + +[] +[] +[] +let ``Regression2296.DirectResultsOfMethodCall`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo").{caret} + """ + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +[] +[] +let ``Regression2296.Identifier.String.Reflection01`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo")(*Marker1*) + let x = "" + let _ = x.Contains("a").{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +[] +[] +let ``Regression2296.Identifier.String.Reflection02`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo")(*Marker1*) + let x = "" + let _ = x.Contains("a")(*Marker2*) + let _ = x.CompareTo("a").{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +[] +[] +let ``Regression2296.System.StaticMethod.Reflection`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo")(*Marker1*) + let x = "" + let _ = x.Contains("a")(*Marker2*) + let _ = x.CompareTo("a")(*Marker3*) + open System.IO + let GetFileSize (filePath: string) = File.GetAttributes(filePath).{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +let ``LongIdent.PInvoke.AsAttribute`` () = + let info = + Checker.getCompletionInfo + """ + open System.IO + open System.Runtime.InteropServices + + module mymodule = + type SomeAttrib() = + inherit System.Attribute() + type myclass() = + member x.name() = "test case" + module mymodule2 = + [] + extern bool CopyFile_Attrib([] char [] lpExistingFileName, char []lpNewFileName, [] bool & bFailIfExists); + + let result5 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) + printfn "WithAttribute %A" result5""" + + assertHasItemWithNames [ "SomeAttrib" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs new file mode 100644 index 00000000000..43e34524a48 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs @@ -0,0 +1,17 @@ +module FSharp.Compiler.Service.Tests.CompletionByrefSpansTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CLIEventsWithByRefArgs`` () = + let info = + Checker.getCompletionInfo + """type MyDelegate = delegate of obj * string byref -> unit +type mytype() = [] member this.myEvent = (new DelegateEvent()).Publish +let t = mytype() +t.{caret}""" + + assertHasItemWithNames [ "add_myEvent"; "remove_myEvent" ] info + assertHasNoItemsWithNames [ "myEvent" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs new file mode 100644 index 00000000000..f576c7339e8 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs @@ -0,0 +1,256 @@ +module FSharp.Compiler.Service.Tests.CompletionClassesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AutoCompletion.BeforeThis`` () = + let plain = + Checker.getCompletionInfo + """type A() = + member _.X = () + member this.{caret}""" + + let privateMember = + Checker.getCompletionInfo + """type A() = + member _.X = () + member private this.{caret}""" + + let publicMember = + Checker.getCompletionInfo + """type A() = + member _.X = () + member public this.{caret}""" + + let internalMember = + Checker.getCompletionInfo + """type A() = + member _.X = () + member internal this.{caret}""" + + Assert.Equal(0, plain.Items.Length) + Assert.Equal(0, privateMember.Items.Length) + Assert.Equal(0, publicMember.Items.Length) + Assert.Equal(0, internalMember.Items.Length) + +[] +let ``Completion.DetectInvalidCompletionContext`` () = + let dotOnly = + Checker.getCompletionInfo + """type X = + inherit System {caret}.""" + + let dotCollections = + Checker.getCompletionInfo + """type X = + inherit System {caret}.Collections""" + + Assert.Equal(0, dotOnly.Items.Length) + Assert.Equal(0, dotCollections.Items.Length) + +[] +let ``Completion.LongIdentifiers`` () = + let trailingSpaces = + Checker.getCompletionInfo + """type X = + inherit System. {caret}""" + + let nextLineComment = + Checker.getCompletionInfo + """type X = + inherit System. + {caret}""" + + let leadingDotNextLine = + Checker.getCompletionInfo + """type X = + inherit System + .{caret}""" + + let moduleCandidates = + Checker.getCompletionInfo + """module Mod = + let x = 1 +module Mod2 = + let x = 1 +type X = + inherit Mod{caret}""" + + let partialSystem = + Checker.getCompletionInfo + """type X = + inherit Sys{caret}""" + + let partialCollection = + Checker.getCompletionInfo + """type X = + inherit System.Col{caret}lection""" + + let dotSpaceCollections = + Checker.getCompletionInfo + """type X = + inherit System. {caret} Collections""" + + let dotSpaceArrayList = + Checker.getCompletionInfo + """type X = + inherit System. {caret} Collections.ArrayList()""" + + assertHasItemWithNames [ "IDisposable"; "Array" ] trailingSpaces + assertHasItemWithNames [ "IDisposable"; "Array" ] nextLineComment + assertHasItemWithNames [ "IDisposable"; "Array" ] leadingDotNextLine + assertHasItemWithNames [ "Mod"; "Mod2" ] moduleCandidates + assertHasItemWithNames [ "System"; "obj" ] partialSystem + assertHasItemWithNames [ "Collections"; "IDisposable" ] partialCollection + assertHasItemWithNames [ "Collections"; "IDisposable" ] dotSpaceCollections + assertHasItemWithNames [ "Collections"; "IDisposable" ] dotSpaceArrayList + +[] +let ``AfterConstructor.5039_1`` () = + let info = + Checker.getCompletionInfo + """let someCall(x) = null +let xe = someCall(System.IO.StringReader().{caret}""" + + assertHasItemWithNames [ "ReadBlock" ] info + assertHasNoItemsWithNames [ "LastIndexOfAny" ] info + +[] +let ``AfterConstructor.5039_1.CoffeeBreak`` () = + let info = + Checker.getCompletionInfo + """let someCall(x) = null +let xe = someCall(System.IO.StringReader().{caret}""" + + assertHasItemWithNames [ "ReadBlock" ] info + assertHasNoItemsWithNames [ "LastIndexOfAny" ] info + +[] +let ``AfterConstructor.5039_2`` () = + let info = Checker.getCompletionInfo "System.Random().{caret}" + + assertHasItemWithNames [ "NextDouble" ] info + +[] +let ``AfterConstructor.5039_4`` () = + let info = Checker.getCompletionInfo "System.Collections.Generic.List().{caret}" + + assertHasItemWithNames [ "BinarySearch" ] info + +[] +let ``NameSpace.AsConstructor`` () = + let info = Checker.getCompletionInfo "new System.DateTime({caret})" + + assertHasItemWithNames [ "System"; "Array2D" ] info + assertHasNoItemsWithNames [ "DaysInMonth"; "AddDays" ] info + +[] +let ``Bug243082.DotAfterNewBreaksCompletion`` () = + let info = + Checker.getCompletionInfo + """module A = + type B() = class end +let s = 1 +s.{caret} +let z = new A.""" + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +let bug2884Cases: obj[] seq = + [ + [| box "type T1(aaa1) =\n do ({caret}"; box [ "aaa1" ] |] + [| box "type T1(aaa1) =\n do ({caret}\nlet a = 0"; box [ "aaa1" ] |] + [| box "type T1(aaa1) =\n member x.Foo(aaa2) = \n do ({caret}\n member x.Bar = 0"; box [ "aaa1"; "aaa2" ] |] + [| box "type T1(aaa1) =\n member x.Foo(aaa2) = \n let dt = new System.DateTime({caret}"; box [ "aaa1"; "aaa2" ] |] + ] + +[] +let ``Parameter.Bug2884`` (source: string) (expected: string list) = + assertHasItemWithNames expected (Checker.getCompletionInfo source) + +[] +let ``CaseInsensitive`` () = + let info = + Checker.getCompletionInfo + """ + type Test() = + member this.Xyzzy = () + member this.xYzzy = () + member this.xyZzy = () + member this.xyzZy = () + member this.xyzzY = () + let t = new Test() + t.XYZ{caret} + """ + + assertHasItemWithNames [ "Xyzzy"; "xYzzy"; "xyZzy"; "xyzZy"; "xyzzY" ] info + +[] +let ``ObjInstance.InheritedClass.MethodsDefInBase`` () = + let info = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + dog.{caret}""" + + assertHasItemWithNames [ "Name"; "dog" ] info + +[] +[] // Class.Self.Bug1544 +[] // MemberSelf +[] // Identifier.AsClassName.InInitial +let ``Identifier.DeclarationPositionDotIsEmpty`` (caseId: int) = + let source = + match caseId with + | 153 + | 441 -> + """ + type Foo() = + member this.{caret}""" + | _ -> + """ + type f1.{caret} = + val field: int""" + + let info = Checker.getCompletionInfo source + + Assert.Equal(0, info.Items.Length) + +[] +let ``SelfParameter.InDoKeywordScope`` () = + let info = + Checker.getCompletionInfo + """ + type foo() as this = + do + this.{caret}""" + + assertHasItemWithNames [ "ToString" ] info + +[] +let ``SelfParameter.InDoKeywordScope.Negative`` () = + let info = + Checker.getCompletionInfo + """ + type foo() as this = + do + this.{caret}""" + + assertHasNoItemsWithNames [ "Value"; "Contents" ] info + +[] +let ``AutoComplete.Bug72596_A`` () = + let info = + Checker.getCompletionInfo + """type ClassType() = + let foo = fo{caret}""" + + assertHasNoItemsWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs new file mode 100644 index 00000000000..bf7d3b31ea8 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs @@ -0,0 +1,559 @@ +module FSharp.Compiler.Service.Tests.CompletionComputationExpressionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AsyncExpression.CtrlSpaceSmokeTest3d`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + let x = async { for xxxxxx in [1;2;3] do xxx{caret} }""" + + assertHasItemWithNames [ "xxxxxx" ] info + +[] +let ``SequenceExpressions.SequenceExprWithWhileLoopSystematic`` () = + let prefix = "\nmodule Test\nlet abbbbc = [| 1 |]\nlet aaaaaa = 0\n" + + let suffixes = + [ "" + " }" + " } \nlet nextDefinition () = 1\n" + " \nlet nextDefinition () = 1\n" + " \ntype NextDefinition() = member x.P = 1\n" ] + + let lines = + [ "BL1", "let f() = seq { while abb(*C*)", [ "(*C*)", false, [ "abbbbc" ] ] + "BL2", "let f() = seq { while abbbbc(*D1*)", [ "(*D1*)", true, [ "Length" ] ] + "BL3", "let f() = seq { while abbbbc(*D1*) do (*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc" ] ] + "BL4", "let f() = seq { while abbbbc(*D1*) do abb(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc" ] ] + "BL5", "let f() = seq { while abbbbc(*D1*) do abbbbc(*D2*)", [ "(*D1*)", true, [ "Length" ]; "(*D2*)", true, [ "Length" ] ] + "BL6", "let f() = seq { while abbbbc(*D1*) do abbbbc.[(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc"; "aaaaaa" ] ] + "BL7", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7a", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)]", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7b", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- ", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7c", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- 1", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7d", "let f() = seq { while abbbbc(*D1*) do abbbbc.[ (*C*) ] <- 1", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL8", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa]", [ "(*D1*)", true, [ "Length" ] ] + "BL9", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- (*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc"; "aaaaaa" ] ] + "BL10", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- aaa(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] ] + + for suffix in suffixes do + for (lineName, lineText, checks) in lines do + for (marker, dot, expected) in checks do + let replacement = if dot then ".{caret}" else "{caret}" + let markedSource = prefix + lineText.Replace(marker, replacement) + suffix + let info = Checker.getCompletionInfo markedSource + let itemNames = info.Items |> Array.map (fun i -> i.NameInCode) + + for name in expected do + if not (Array.contains name itemNames) then + failwithf + "suffix=%A line=%s marker=%s: expected %s but got [%s]" + suffix + lineName + marker + name + (String.concat ", " itemNames) + +[] +let ``ComputationExpression.LetBang`` () = + let info = + Checker.getCompletionInfo + """let http(url:string) = + async { + let rnd = new System.Random() + let! rsp = rnd.{caret}N""" + + assertHasItemWithNames [ "Next" ] info + +[] +let ``CompletionInDifferentEnvs3`` () = + let info = + Checker.getCompletionInfo + """let mb1 = new MailboxProcessor>(fun inbox -> async { let! msg = inbox.Receive() + do {caret}""" + + assertHasItemWithNames [ "msg" ] info + +[] +let ``CompletionInDifferentEnvs4`` () = + let info1 = + Checker.getCompletionInfo + """async { + let! x = i + ({caret} +}""" + + assertHasItemWithNames [ "x" ] info1 + + let info2 = + Checker.getCompletionInfo + """let q = + let a = 20 + let b = (fun i -> i) 40 + (({caret}""" + + assertHasItemWithNames [ "b" ] info2 + assertHasNoItemsWithNames [ "i" ] info2 + +[] +let ``CompletionForAndBang_BaseLine0`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +builder { + let! xxx3 = 2 + return x{caret} +}""" + + assertHasItemWithNames [ "xxx3" ] info + +[] +let ``CompletionForAndBang_BaseLine1`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let xxx1 = 1 +builder { + let xxx2 = 1 + let! xxx3 = 1 + return (1 + x{caret}) +}""" + + assertHasItemWithNames [ "xxx1"; "xxx2"; "xxx3" ] info + +[] +let ``CompletionForAndBang_BaseLine2`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let yyy1 = 1 +builder { + let yyy2 = 1 + let! yyy3 = 1 + return (1 + y{caret})""" + + assertHasItemWithNames [ "yyy1"; "yyy2"; "yyy3" ] info + +[] +let ``CompletionForAndBang_BaseLine3`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let zzz2 = 1 + let! zzz3 = 1 + return (1 + z{caret}""" + + assertHasItemWithNames [ "zzz1"; "zzz2"; "zzz3" ] info + +[] +let ``CompletionForAndBang_BaseLine4`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let! zzz3 = 1 + return (1 + z{caret}""" + + assertHasItemWithNames [ "zzz1"; "zzz3" ] info + +[] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return0`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.MergeSources(a: 'T1, b: 'T2) = (a, b) + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +builder { + let! xxx3 = 2 + and! xxx4 = 2 + return x{caret} +}""" + + assertHasItemWithNames [ "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return1`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.MergeSources(a: 'T1, b: 'T2) = (a, b) + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let xxx1 = 1 +builder { + let xxx2 = 1 + let! xxx3 = 1 + and! xxx4 = 1 + return (1 + x{caret}) +}""" + + assertHasItemWithNames [ "xxx1"; "xxx2"; "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return2`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.MergeSources(a: 'T1, b: 'T2) = (a, b) + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let yyy1 = 1 +builder { + let yyy2 = 1 + let! yyy3 = 1 + and! yyy4 = 1 + return (1 + y{caret})""" + + assertHasItemWithNames [ "yyy1"; "yyy2"; "yyy3"; "yyy4" ] info + +[] +[ 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let zzz2 = 1 + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz2 zzz3 zzz4")>] +[ 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz3 zzz4")>] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return3and4`` (markedSource: string) (expectedNames: string) = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + markedSource + + assertHasItemWithNames (expectedNames.Split(' ') |> List.ofArray) info + +[] +let ``CompletionForAndBang_Test_Bind2Return0`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b) +let builder = Builder() +builder { + let! xxx3 = 2 + and! xxx4 = 2 + return x{caret} +}""" + + assertHasItemWithNames [ "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_Bind2Return1`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b) +let builder = Builder() +let xxx1 = 1 +builder { + let xxx2 = 1 + let! xxx3 = 1 + and! xxx4 = 1 + return (1 + x{caret}) +}""" + + assertHasItemWithNames [ "xxx1"; "xxx2"; "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_Bind2Return2`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b) +let builder = Builder() +let yyy1 = 1 +builder { + let yyy2 = 1 + let! yyy3 = 1 + and! yyy4 = 1 + return (1 + y{caret})""" + + assertHasItemWithNames [ "yyy1"; "yyy2"; "yyy3"; "yyy4" ] info + +[] +[ 'T3) = f (a, b) +let builder = Builder() +let zzz1 = 1 +builder { + let zzz2 = 1 + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz2 zzz3 zzz4")>] +[ 'T3) = f (a, b) +let builder = Builder() +let zzz1 = 1 +builder { + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz3 zzz4")>] +let ``CompletionForAndBang_Test_Bind2Return3and4`` (markedSource: string) (expectedNames: string) = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + markedSource + + assertHasItemWithNames (expectedNames.Split(' ') |> List.ofArray) info + +[] +let ``Expressions.Computation`` () = + let info = + Checker.getCompletionInfo + """type FooBuilder() = + member x.Return(a) = new System.Random() +let foo = FooBuilder() +(foo { return 0 }).{caret}""" + + assertHasItemWithNames [ "Next" ] info + assertHasNoItemsWithNames [ "GetEnumerator" ] info + +[] +let ``ComputationExpressionLet`` () = + let info = + Checker.getCompletionInfo + """let http(url:string) = + async { + let rnd = new System.Random() + let rsp = rnd.{caret}N""" + + assertHasItemWithNames [ "Next" ] info + +[] +let ``InAsyncAndUseBlock`` () = + let info = + Checker.getCompletionInfo + """ + open System.Text.RegularExpressions + open System.IO + let collectLinksAsync (url:string) : Async = + async { do printfn "requesting %s" url + let! html = + async { use reader = new System.IO.StreamReader(new System.IO.FileStream("", FileMode.CreateNew)) + do printfn "reading %s" url + return {caret}reader.ReadToEnd() } //<---- reader + let links = "a" + return links } + """ + + assertHasItemWithNames [ "reader" ] info + +[] +let ``ComputationExpression.WithClosingBrace`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3879: intellisense glitch for computation expression + // intellisense does not work in computation expression without the closing brace + type System.Net.WebRequest with + member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) + member x.GetResponseAsync() = x.AsyncGetResponse() + let http(url:string) = + async {let req = System.Net.WebRequest.Create("http://www.yahoo.com") + let! rsp = req.{caret}} """ + + assertHasItemWithNames [ "AsyncGetResponse"; "GetResponseAsync"; "ToString" ] info + +[] +let ``ComputationExpression.WithoutClosingBrace`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3879: intellisense glitch for computation expression + // intellisense does not work in computation expression without the closing brace + type System.Net.WebRequest with + member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) + member x.GetResponseAsync() = x.AsyncGetResponse() + let http(url:string) = + async { let req = System.Net.WebRequest.Create("http://www.yahoo.com") + let! rsp = req.{caret}""" + + assertHasItemWithNames [ "AsyncGetResponse"; "GetResponseAsync"; "ToString" ] info + +[] +let ``AutoComplete.Bug69654_1`` () = + let info1 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.Comp{caret}areTo |> ignore // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "CompareTo" ] info1 + + let info2 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + x{caret}xx.CompareTo |> ignore // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info2 + + let info3 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.CompareTo |> ignore // the dot works + x{caret}xx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info3 + + let info4 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.CompareTo |> ignore // the dot works + xxx |> ignore // no xxx + do xx{caret}x |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info4 + + let info5 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.CompareTo |> ignore // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xx{caret}x // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info5 + +[] +let ``AutoComplete.Bug69654_2`` () = + let info1 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Disp{caret}ose() // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "Dispose" ] info1 + + let info2 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + x{caret}xx.Dispose() // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info2 + + let info3 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Dispose() // the dot works + x{caret}xx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info3 + + let info4 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Dispose() // the dot works + xxx |> ignore // no xxx + do xx{caret}x |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info4 + + let info5 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Dispose() // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xx{caret}x // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info5 + +[] +let ``EnsureThatUnhandledExceptionsCauseAnAssert`` () = () diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs new file mode 100644 index 00000000000..b0faf6e55b7 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs @@ -0,0 +1,79 @@ +module FSharp.Compiler.Service.Tests.CompletionConditionalsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ValueDeclarationHidden.Bug4405`` () = + let info = + Checker.getCompletionInfo + """do + let a = "string" + let a = if true then 0 else a.{caret}""" + + assertHasItemWithNames [ "IndexOf"; "Substring" ] info + +[] +let ``Parameter.DirectAfterDefined.Bug2884`` () = + let info = + Checker.getCompletionInfo + """if true then + let aaa1 = 0 + ({caret}""" + + assertHasItemWithNames [ "aaa1" ] info + +[] +let ``COMPILED.DefineNotPropagatedToIncrementalBuilder`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "--define:COMPILED" |] + FSharpCodeCompletionOptions.Default + """module File1 = +#if COMPILED + let x = 0 +#else + let y = 1 +#endif + +module File2 = + File1.{caret}""" + + assertHasItemWithNames [ "x" ] info + assertHasNoItemsWithNames [ "y" ] info + Assert.Equal(1, info.Items.Length) + +[] +let ``Keywords.If`` () = + let info = + Checker.getCompletionInfo + """ + if.{caret} true then + () """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``NotShowPInvokeSignature`` () = + let info = + Checker.getCompletionInfo + """let x = "System.Console" +#if RELEASE +System.Console.{caret} +#endif +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Regression4405.Identifier.ReBound`` () = + let info = + Checker.getCompletionInfo + """ + let f x = + let varA = "string" + let varA = if x then varA.{caret} else 2 + varA""" + + assertHasItemWithNames [ "Chars"; "StartsWith" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs new file mode 100644 index 00000000000..9dd4005c8ac --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs @@ -0,0 +1,89 @@ +module FSharp.Compiler.Service.Tests.CompletionConstraintsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AutoCompletion.OnTypeConstraintError`` () = + let info = + Checker.getCompletionInfo + """type Foo = Foo + with + member _.Bar = 1 + member _.PublicMethodForIntellisense() = 2 + member internal _.InternalMethod() = 3 + member private _.PrivateProperty = 4 + +let u: Unit = + [ Foo ] + |> List.map (fun abcd -> abcd.{caret})""" + + assertHasItemWithNames [ "Bar"; "Equals"; "GetHashCode"; "GetType"; "InternalMethod"; "PublicMethodForIntellisense"; "ToString" ] info + +[] +let ``ConstrainedTypes`` () = + let info1 = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + let pet = dog :> Pet + pet.{caret} + let dctest = pet :?> Dog + dctest(*Mdowncast*) + let f (x : bigint) = x(*Mconstrainedtoint*) + """ + + assertHasItemWithNames [ "Name"; "Speak" ] info1 + + let info2 = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + let pet = dog :> Pet + pet(*Mupcast*) + let dctest = pet :?> Dog + dctest.{caret} + let f (x : bigint) = x(*Mconstrainedtoint*) + """ + + assertHasItemWithNames [ "dog"; "Name" ] info2 + + let info3 = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + let pet = dog :> Pet + pet(*Mupcast*) + let dctest = pet :?> Dog + dctest(*Mdowncast*) + let f (x : bigint) = x.{caret} + """ + + assertHasItemWithNames [ "ToString" ] info3 + +[] +let ``Identifier.EqualityConstraint.Bug65730`` () = + let info = + Checker.getCompletionInfo + """let g3<'a when 'a : equality> (x:'a) = x.{caret}""" + + assertHasItemWithNames [ "Equals"; "GetHashCode" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..e540564a36a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs @@ -0,0 +1,185 @@ +module FSharp.Compiler.Service.Tests.CompletionDiscriminatedUnionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AutoCompletion.ObjectMethods`` () = + let source (tail: string) = + sprintf + """type DU1 = DU_1 +[] +type DU2 = DU_2 +[] +type DU3 = + | DU_3 + with member this.Equals(b : string) = 1 +[] +type DU4 = + | DU_4 + with member this.GetHashCode(b : string) = 1 +module Extensions = + type System.Object with + member this.ExtensionPropObj = 42 + member this.ExtensionMethodObj () = 42 +open Extensions +%s""" + tail + + let cases = + [ "obj().{caret}", [ "Equals"; "ExtensionPropObj"; "ExtensionMethodObj" ], [] + "System.Object.{caret}", [ "Equals"; "ReferenceEquals" ], [] + "System.String.{caret}", [ "Equals" ], [] + "DU_1.{caret}", [ "Equals"; "GetHashCode"; "ExtensionMethodObj"; "ExtensionPropObj" ], [] + "DU_2.{caret}", [ "ExtensionPropObj"; "ExtensionMethodObj" ], [ "Equals"; "GetHashCode" ] + "DU_3.{caret}", [ "ExtensionPropObj"; "ExtensionMethodObj"; "Equals" ], [ "GetHashCode" ] + "DU_4.{caret}", [ "ExtensionPropObj"; "ExtensionMethodObj"; "GetHashCode" ], [ "Equals" ] ] + + for tail, expected, notExpected in cases do + let info = Checker.getCompletionInfo (source tail) + assertHasItemWithNames expected info + + if not (List.isEmpty notExpected) then + assertHasNoItemsWithNames notExpected info + +[] +let ``SimpleTypes.DisUnion`` () = + let info = + Checker.getCompletionInfo + """ + type Route = int + type Make = string + type Model = string + type Transport = + | Car of Make * Model + | Bicycle + | Bus of Route + let typediscriminatedunion = Car("BMW","360") + typediscriminatedunion.{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info + +[] +let ``VariableIdentifier.MethodsInheritFromBase`` () = + let info = + Checker.getCompletionInfo + """ + namespace MyNamespace1 + module MyModule = + type DuType = + | Tag of int + let f (DuType(*Maftervariable1*).Tag(x)) = 10 + type Pet() = + member x.Name = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + do base.{caret}GetType() + let dog = new Dog()""" + + assertHasItemWithNames [ "Name"; "Speak" ] info + +[] +[ = [1; 2; 3] + let f (x:MyNamespace1.MyModule.{caret}) = 10 + let y = int System.IO(*Maftervariable5*)""", + "DuType")>] +[ = [1; 2; 3] + let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 + let y = int System.IO.{caret}""", + "BinaryReader;Stream;Directory")>] +let ``VariableIdentifier.DefInDiffNamespace`` (markedSource: string) (names: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames (names.Split(';') |> List.ofArray) info + +[] +[] 'a> = 10""", + "Dog;DuType")>] +[] 'a> = 10""", + "Tag")>] +let ``LongIdent.AsTypeParameter.DefInDiffNamespace`` (markedSource: string) (names: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames (names.Split(';') |> List.ofArray) info + +[] +let ``Identifier.InDiscUnion.WithoutDef`` () = + let info = + Checker.getCompletionInfo + """ + type DUTag = + |Tag.{caret} of int""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``VariableIdentifier.AsParameter`` () = + let info = + Checker.getCompletionInfo + """ + module MyModule = + type DuType = + | Tag of int + let f (DuType.{caret}Tag(x)) = 10 """ + + assertHasItemWithNames [ "Tag" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs new file mode 100644 index 00000000000..6c68f7ebd26 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs @@ -0,0 +1,174 @@ +module FSharp.Compiler.Service.Tests.CompletionEnumsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``OfSeveralModuleMembers`` () = + let completeAt (expr: string) = + Checker.getCompletionInfo ( + sprintf + """module Module = + let Constant = 5 + type Class = class + end + type Record = {AString:string} + exception OutOfRange of string + type Enum = Red = 0 | White = 1 | Blue = 2 + type DiscriminatedUnion = A | B | C + type TupleType = int * int + type FunctionType = unit->unit + let (~+) x = -x + type Interface = + abstract MyMethod : unit->unit + type Struct = struct + end + let Function x = 0 + let FunctionValue = fun x -> 0 + let Tuple = (0,2) + module Submodule = + let a = 0 + type ValueType = int +module AbbreviationModule = + type StructAbbreviation = Module.Struct + type InterfaceAbbreviation = Module.Interface + type DiscriminatedUnionAbbreviation = Module.DiscriminatedUnion + type RecordAbbreviation = Module.Record + type EnumAbbreviation = Module.Enum + type TupleTypeAbbreviation = Module.TupleType +let y = %s +let f x = 0""" + expr) + + let moduleMembers = completeAt "Module.{caret}" + + assertHasItemWithNames + [ "Constant"; "Class"; "Record"; "OutOfRange"; "Enum"; "DiscriminatedUnion"; "TupleType" + "FunctionType"; "Interface"; "Struct"; "Function"; "FunctionValue"; "Tuple"; "Submodule"; "ValueType" ] + moduleMembers + + for name, glyph in + [ "A", FSharpGlyph.EnumMember + "B", FSharpGlyph.EnumMember + "C", FSharpGlyph.EnumMember + "Enum", FSharpGlyph.Enum + "DiscriminatedUnion", FSharpGlyph.Union + "Interface", FSharpGlyph.Interface + "Struct", FSharpGlyph.Struct + "ValueType", FSharpGlyph.Struct + "Class", FSharpGlyph.Class + "Record", FSharpGlyph.Type + "TupleType", FSharpGlyph.Class + "FunctionType", FSharpGlyph.Delegate + "Submodule", FSharpGlyph.Module + "OutOfRange", FSharpGlyph.Exception + "Function", FSharpGlyph.Method + "FunctionValue", FSharpGlyph.Method + "Constant", FSharpGlyph.Variable + "Tuple", FSharpGlyph.Variable ] do + assertItemGlyph name glyph moduleMembers + + let abbreviationMembers = completeAt "AbbreviationModule.{caret}" + + assertHasItemWithNames + [ "StructAbbreviation"; "InterfaceAbbreviation"; "DiscriminatedUnionAbbreviation" + "RecordAbbreviation"; "EnumAbbreviation"; "TupleTypeAbbreviation" ] + abbreviationMembers + + for name, glyph in + [ "EnumAbbreviation", FSharpGlyph.Enum + "InterfaceAbbreviation", FSharpGlyph.Interface + "StructAbbreviation", FSharpGlyph.Struct + "RecordAbbreviation", FSharpGlyph.Type + "DiscriminatedUnionAbbreviation", FSharpGlyph.Union + "TupleTypeAbbreviation", FSharpGlyph.Class ] do + assertItemGlyph name glyph abbreviationMembers + +[] +let ``EnumValue.Bug2449`` () = + let info = + Checker.getCompletionInfo + """type E = | A = 1 | B = 2 +let e = E.A +e.{caret}""" + + assertHasNoItemsWithNames [ "value__" ] info + +[] +let ``EnumValue.Bug4044`` () = + let info = + Checker.getCompletionInfo + """open System.IO +let GetFileSize filePath = File.GetAttributes(filePath).{caret}""" + + assertHasNoItemsWithNames [ "value__" ] info + +[] +let ``SimpleTypes.Enum`` () = + let info = + Checker.getCompletionInfo + """ + type weekday = + | Monday = 1 + | Tuesday = 2 + | Wednesday = 3 + | Thursday = 4 + | Friday = 5 + let typeenum = weekday.Friday + typeenum.{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info + +[] +[ "move left" + | NS(*Mpatternmatch2*) -> "move right" """, + "Direction;ToString")>] +[ "move left" + | NS.{caret} -> "move right" """, + "longident")>] +let ``LongIdent.PatternMatch.DefFromDiffNamespace`` (markedSource: string) (names: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames (names.Split(';') |> List.ofArray) info + +[] +let ``ReOpenNameSpace.EnumTypes`` () = + let info = + Checker.getCompletionInfo + """ + // F# declared enum types: + namespace A + module Test = + type A = | Foo = 0 + namespace B + open A + open A + Test.A.{caret} + """ + + assertHasItemWithNames [ "Foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs new file mode 100644 index 00000000000..becc3a2cb3a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs @@ -0,0 +1,48 @@ +module FSharp.Compiler.Service.Tests.CompletionEventsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CLIEvents.DefinedInAssemblies.Bug787438`` () = + let info = + Checker.getCompletionInfo + """let mb = new MailboxProcessor(fun _ -> ()) +mb.{caret}""" + + assertHasItemWithNames [ "Error" ] info + assertHasNoItemsWithNames [ "add_Error"; "remove_Error" ] info + +[] +let ``Event.NonStandard.PrefixMethods`` () = + let info = + Checker.getCompletionInfo + """System.AppDomain.CurrentDomain.{caret}""" + + assertHasItemWithNames [ "add_AssemblyResolve"; "remove_AssemblyResolve"; "add_ReflectionOnlyAssemblyResolve"; "remove_ReflectionOnlyAssemblyResolve"; "add_ResourceResolve"; "remove_ResourceResolve"; "add_TypeResolve"; "remove_TypeResolve" ] info + +[] +let ``Event.NonStandard.VerifyLegitimateNameShowUp`` () = + let info = + Checker.getCompletionInfo + """System.AppDomain.CurrentDomain.{caret}""" + + assertHasItemWithNames [ "AssemblyResolve"; "ReflectionOnlyAssemblyResolve"; "ResourceResolve"; "TypeResolve" ] info + +[] +let ``ReOpenNameSpace.StaticProperties`` () = + let info = + Checker.getCompletionInfo + """ + // Static properties & events + namespace A + type TestType = + static member Prop = 0 + static member Event = (new Event()).Publish + namespace B + open A + open A + TestType.{caret}""" + + assertHasItemWithNames [ "Prop"; "Event" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs new file mode 100644 index 00000000000..9e702dcbfc0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs @@ -0,0 +1,69 @@ +module FSharp.Compiler.Service.Tests.CompletionExceptionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``IncompleteStatement.Try_B`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +try (x).{caret} finally ()""" + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``IncompleteStatement.Try_C`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +try (x).{caret} with e -> () """ + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``Duplicates.Bug4103b`` () = + let source marker = + sprintf + """namespace A +module Test = + let foo n = n + 1 + let (|Pat|) x = x + 1 + exception Failed + type Del = delegate of int -> int + type A = | Foo + type B = | Bar = 0 +type TestType = + static member Prop = 0 + static member Event = (new Event<_>()).Publish +namespace B +open A +open A +%s""" + marker + + for marker, shortName, fullName in + [ "Test.", "foo", "foo" + "Test.", "Pat", "Pat" + "Test.", "Failed", "exception Failed" + "Test.", "Del", "type Del" + "Test.", "Foo", "Test.A.Foo" + "Test.B.", "Bar", "Test.B.Bar" + "TestType.", "Prop", "TestType.Prop" + "TestType.", "Event", "TestType.Event" ] do + let info = Checker.getCompletionInfo (source (marker + "{caret}")) + + assertItemDescriptionContainsExactlyOnce shortName fullName info + +[] +let ``NoDupException.Postive`` () = + let info = Checker.getCompletionInfo """let x = Match{caret}""" + + assertHasItemWithNames [ "MatchFailureException" ] info + +[] +let ``DotNetException.Negative`` () = + let info = Checker.getCompletionInfo """let x = Match{caret}""" + + assertHasNoItemsWithNames [ "MatchFailure" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs new file mode 100644 index 00000000000..32d20a5c257 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs @@ -0,0 +1,200 @@ +module FSharp.Compiler.Service.Tests.CompletionFunctionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``DotAfterApplication1`` () = + let info = + Checker.getCompletionInfo + """let g a = new System.Random() +(g []).{caret}""" + + assertHasItemWithNames [ "Next" ] info + +[] +let ``DotAfterApplication2`` () = + let info = + Checker.getCompletionInfo + """let g a = new System.Random() +g [].{caret}""" + + assertHasItemWithNames [ "Head" ] info + +[] +let ``CurriedArguments.Regression1`` () = + let info = + Checker.getCompletionInfo + """let f{caret}ffff x y = 1 +let ggggg = 1 +let test1 = fffff "a" ggggg +let test2 = fffff 1 ggggg +let test3 = fffff ggggg ggggg""" + + assertHasItemWithNames [ "fffff" ] info + +[] +[] +[] +[] +[] +[] +let ``CurriedArguments.Regression`` (markedSource: string) (expected: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ expected ] info + +[] +let ``StringFunctions`` () = + let info = + Checker.getCompletionInfo + """let y = String.{caret} +let f x = 0""" + + assertHasItemWithNames [ "collect"; "concat"; "exists" ] info + + for item in info.Items do + Assert.Equal(FSharpGlyph.Method, item.Glyph) + +[] +let ``NotShowInfo.FunctionParameter.Bug3602`` () = + let info = + Checker.getCompletionInfo + """let foo s.{caret} = s + "Hello world" + ()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``IncompleteIfClause.Bug4594`` () = + let info = + Checker.getCompletionInfo + """let Bar(xyz) = + let hello = + if x{caret}""" + + assertHasItemWithNames [ "xyz" ] info + +[] +let ``ListFunctions`` () = + let info = + Checker.getCompletionInfo + """let y = List.{caret} +let f x = 0""" + + assertHasItemWithNames [ "map"; "filter"; "fold" ] info + + for item in info.Items do + match item.NameInCode, item.Glyph with + | "Cons", FSharpGlyph.Method -> () + | "Empty", FSharpGlyph.Property -> () + | "empty", _ -> () + | _, FSharpGlyph.Method -> () + | name, glyph -> Assert.Fail(sprintf "Unexpected item %s with glyph %A" name glyph) + +[] +let ``Expression.Function`` () = + let info = + Checker.getCompletionInfo + """ + let func(mm) = 100 + func(x + y).{caret} + """ + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +[] +[] +let ``RedefinedIdentifier.DiffScope.InScope`` (item: string) (shouldBePresent: bool) = + let info = + Checker.getCompletionInfo + """ + let identifierBothScope = "" + let functionScope () = + let identifierBothScope = System.DateTime.Now + identifierBothScope.{caret} + identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""" + + if shouldBePresent then + assertHasItemWithNames [ item ] info + else + assertHasNoItemsWithNames [ item ] info + +[] +let ``RedefinedIdentifier.DiffScope.OutScope.Positive`` () = + let info = + Checker.getCompletionInfo + """ + let identifierBothScope = "" + let functionScope () = + let identifierBothScope = System.DateTime.Now + identifierBothScope(*MarkerShowLastOneWhenInScope*) + identifierBothScope.{caret}""" + + assertHasItemWithNames [ "Chars" ] info + +[] +let ``Identifier.AsFunctionName.InInitial`` () = + let info = + Checker.getCompletionInfo + """let f2.{caret} x = x+1 """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.AsParameter.InInitial`` () = + let info = + Checker.getCompletionInfo + """ let f3 x.{caret} = x+1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Basic.Completion.UnfinishedLet`` () = + let info = + Checker.getCompletionInfo + """ + let g(x) = x+1 + let f() = + let r = g(4).{caret} """ + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``AutoComplete.Bug65730`` () = + let info = + Checker.getCompletionInfo + """let f x y = x.{caret}Equals(y)""" + + assertHasItemWithNames [ "Equals" ] info + +[] +let ``AutoComplete.Bug72596_B`` () = + let info = + Checker.getCompletionInfo + """let f() = + let foo = fo{caret}""" + + assertHasNoItemsWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs new file mode 100644 index 00000000000..100036cdd22 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs @@ -0,0 +1,174 @@ +module FSharp.Compiler.Service.Tests.CompletionGenericsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AfterConstructor.5039_3`` () = + let info = + Checker.getCompletionInfo + """ +System.Collections.Generic.List().{caret}""" + + assertHasItemWithNames [ "BinarySearch" ] info + +let private genericsPreamble = """ +type GT<'a> = + static member P = 12 + static member Q = 13 +type GT2 = + static member R = 12 + static member S = 13 +type D = | DD +let td = typeof +let f i = typeof +""" + +let genericsMemberCases: obj[] seq = + [ [| box "let _ = typeof.{caret}"; box [ "Assembly"; "AssemblyQualifiedName" ] |] + [| box "let _ = GT2.{caret}"; box [ "R"; "S" ] |] + [| box "let _ = GT.{caret}"; box [ "P"; "Q" ] |] ] + +[] +let ``Generics member completion`` (completionLine: string) (expected: string list) = + assertHasItemWithNames expected (Checker.getCompletionInfo (genericsPreamble + "\n" + completionLine)) + +[] +let ``GenericType.Self.Bug69673_1.01`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Foo() as this = + inherit Base(th{caret}is) // this + let o = this // this ok + do this.Bar() // this ok, dotting ok + member this.Bar() = ()""" + + assertHasItemWithNames [ "this" ] info + +[] +[] +[] +let ``GenericType.Self.Bug69673_1.CtrlSpaceForThis`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "this" ] info + +[] +let ``GenericType.Self.Bug69673_1.04`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Foo() as this = + inherit Base(this) // this + let o = this // this ok + do this.{caret}Bar() // this ok, dotting ok + member this.Bar() = ()""" + + assertHasItemWithNames [ "Bar" ] info + +[] +let ``GenericType.Self.Bug69673_2.1`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Food() as this = + class + inherit Base(th{caret}is) // this + do + this |> ignore // this (only repros with explicit class/end) + end""" + + assertHasItemWithNames [ "this" ] info + +[] +let ``GenericType.Self.Bug69673_2.2`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Food() as this = + class + inherit Base(this) // this + do + th{caret}is |> ignore // this (only repros with explicit class/end) + end""" + + assertHasItemWithNames [ "this" ] info + +[] +let ``AfterTypeParameter`` () = + let info1 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string.{caret} + + let f x:int -> string(*MarkerParamFunction*) + + let Type2<'a(*MarkerGenericParam*)> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info1.Items.Length) + + let info2 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string(*MarkerDUTypeParam*) + + let f x:int -> string.{caret} + + let Type2<'a(*MarkerGenericParam*)> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info2.Items.Length) + + let info3 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string(*MarkerDUTypeParam*) + + let f x:int -> string(*MarkerParamFunction*) + + let Type2<'a.{caret}> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info3.Items.Length) + + let info4 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string(*MarkerDUTypeParam*) + + let f x:int -> string(*MarkerParamFunction*) + + let Type2<'a(*MarkerGenericParam*)> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info4.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs new file mode 100644 index 00000000000..f98464b92f1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs @@ -0,0 +1,189 @@ +module FSharp.Compiler.Service.Tests.CompletionIndexingSlicingTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``AdjacentToDot.Positive`` (op: string) = + let info = Checker.getCompletionInfo (markAtEndOfMarker ("System.Console" + op) "System.Console.") + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``AdjacentToDot.Negative`` (op: string) = + let info = Checker.getCompletionInfo ("System.Console" + op + "{caret}") + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "BackgroundColor" ] info + +[] +let ``DotOff.Parenthesized.Expr`` () = + let info = + Checker.getCompletionInfo + """let string_of_int (x:int) = x.ToString() +let strs = Array.init 10 string_of_int +let x = (strs.[1]).{caret}""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``DotOff.ArrayIndexerNotation`` () = + let info = + Checker.getCompletionInfo + """let string_of_int (x:int) = x.ToString() +let strs = Array.init 10 string_of_int +let test1 = strs.[1].{caret}""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +[] +[] +[] +let ``DotOff.ArraySliceNotation`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "Length" ] info + +[] +let ``DotOff.DictionaryIndexer`` () = + let info = + Checker.getCompletionInfo + """let dict = new System.Collections.Generic.Dictionary() +let test5 = dict.[1].{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.FuzzyDefined.Bug67133`` () = + let info = + Checker.getCompletionInfo + """let gDateTime (arr: System.DateTime[]) = + arr.[0].{caret}""" + + assertHasItemWithNames [ "AddDays" ] info + +[] +let ``Identifier.FuzzyDefined.Bug67133.Negative`` () = + let info = + Checker.getCompletionInfo + """let gDateTime (arr: DateTime[]) = + arr.[0].{caret}""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Type.Indexers.Bug4898_1`` () = + let info = + Checker.getCompletionInfo + """type Foo(len) = + member this.Value = [1 .. len] +type Bar = + static member ParamProp with get len = new Foo(len) +let n = Bar.ParamProp.{caret}""" + + assertHasItemWithNames [ "ToString" ] info + assertHasNoItemsWithNames [ "Value" ] info + +[] +let ``Type.Indexers.Bug4898_2`` () = + let info = + Checker.getCompletionInfo + """type mytype() = + let instanceArray2 = [|[| "A"; "B" |]; [| "A"; "B" |] |] + let instanceArray = [| "A"; "B" |] + member x.InstanceIndexer + with get(idx) = instanceArray.[idx] + member x.InstanceIndexer2 + with get(idx1,idx2) = instanceArray2.[idx1].[idx2] +let a = mytype() +a.InstanceIndexer2.{caret}""" + + assertHasItemWithNames [ "ToString" ] info + assertHasNoItemsWithNames [ "Chars" ] info + +[] +let ``Expression.ListItem`` () = + let info = + Checker.getCompletionInfo + """ + let a = [1;2;3] + a.[1].{caret} + """ + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +let ``Expression.2DArray`` () = + let info = + Checker.getCompletionInfo + """ + let (a2: int[,]) = Array2.zero_create 10 10 + a2.[1,2].{caret} + """ + + assertHasItemWithNames [ "ToString" ] info + +[] +[] +[] +let ``Expression.ArrayItem`` (names: string, shouldContain: bool) = + let info = + Checker.getCompletionInfo + """ + //regression test for bug 1001 + let str1 = Array.init 10 string + str1.[1].{caret}""" + + let names = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain names info + +[] +let ``Identifier.In#Statement`` () = + let info = + Checker.getCompletionInfo + """ + # 29 "original-test-file.fs" + let argv = System.Environment.GetCommandLineArgs() + let SetCulture() = + if argv.{caret}Length > 2 && argv.[1] = "--culture" then + let cultureString = argv.[2] + """ + + assertHasItemWithNames [ "Length"; "Clone"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs new file mode 100644 index 00000000000..62034bf6cd4 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs @@ -0,0 +1,30 @@ +module FSharp.Compiler.Service.Tests.CompletionInterfacesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Completion.DetectInterfaces`` () = + let info1 = + Checker.getCompletionInfo + """type X = interface + inherit {caret}""" + + assertHasItemWithNames [ "seq" ] info1 + + let info2 = + Checker.getCompletionInfo + """[] +type X = + inherit {caret}""" + + assertHasItemWithNames [ "seq" ] info2 + + let info3 = + Checker.getCompletionInfo + """[] +type X = interface + inherit {caret}""" + + assertHasItemWithNames [ "seq" ] info3 diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs new file mode 100644 index 00000000000..0a0d3a9a3be --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs @@ -0,0 +1,88 @@ +module FSharp.Compiler.Service.Tests.CompletionLambdasTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``DotCompletionInBrokenLambda`` () = + let info = + Checker.getCompletionInfo + """1 |> id (fun x .{caret}> x)""" + + Assert.Equal(0, info.Items.Length) + +[] +[ id (fun) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun) +[ id (fun)""")>] // error appended: 1 |> id (fun) +[ id (fun x > x) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun x > x) +[ id (fun x > x)""")>] // error appended: 1 |> id (fun x > x) +[ id (fun x > ) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun x > ) +[ id (fun x > )""")>] // error appended: 1 |> id (fun x > ) +[ id (fun x -> ) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun x -> ) +[ id (fun x -> )""")>] // error appended: 1 |> id (fun x -> ) +let ``DotCompletionWithBrokenLambda`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "Array" ] info + +[] +let ``LambdaExpression.WithoutClosing.Bug1346c`` () = + let info = + Checker.getCompletionInfo + """let p4 = + let isPalindrome x = + let chars = (string_of_int x).ToCharArray() + let len = chars.{caret} + chars + |> Array.mapi (fun i c -> )""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.InLambdaExpression`` () = + let info = + Checker.getCompletionInfo + """let funcLambdaExp = fun (x:int)-> x.{caret}""" + + assertHasItemWithNames [ "ToString"; "Equals" ] info + +[] +let ``Identifier.AsFunctionName.UsingFunKeyword`` () = + let info = + Checker.getCompletionInfo + """fun f4.{caret} x -> x+1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``AutoComplete.Bug69654_0`` () = + let info = + Checker.getCompletionInfo + """ +let q = + let a = 42 + let b = (fun i -> i) 43 + // i shows up in Ctrl-space list here, b does not + ({caret}) // but in the parens, things are correct again +""" + + assertHasItemWithNames [ "b" ] info + assertHasNoItemsWithNames [ "i" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs new file mode 100644 index 00000000000..501ae5315df --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs @@ -0,0 +1,114 @@ +module FSharp.Compiler.Service.Tests.CompletionLetBindingsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CtrlSpaceCompletion.Bug130670.Case2`` () = + let info = + Checker.getCompletionInfo + """ +let x = 42 +let r = x + 1 {caret}""" + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``InComment`` () = + let info = Checker.getCompletionInfo """ let s = "System.C{caret}" """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``TopLevelIdentifier.AfterPartialToken1`` () = + let info = + Checker.getCompletionInfo + """let foobaz = 1 +(*marker*)fo{caret}""" + + assertHasItemWithNames [ "System"; "Array2D"; "foobaz" ] info + assertHasNoItemsWithNames [ "Int32" ] info + +[] +let ``TopLevelIdentifier.AfterPartialToken2`` () = + let info = + Checker.getCompletionInfo + """let foobaz = 1 +{caret}fo""" + + assertHasItemWithNames [ "System"; "Array2D"; "foobaz" ] info + +[] +let ``NonDotCompletion`` () = + let info = Checker.getCompletionInfo "let x = S{caret}" + + assertHasItemWithNames [ "Some" ] info + +[] +[] +[] +[] +[] +let ``Residues`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "CLIEventAttribute"; "Checked"; "Choice" ] info + +[] +let ``CompletionInDifferentEnvs2`` () = + let info = + Checker.getCompletionInfo + """let aaa = 1 +let aab = 2 +(aa{caret} +let aac = 3""" + + assertHasItemWithNames [ "aaa"; "aab" ] info + assertHasNoItemsWithNames [ "aac" ] info + +[] +let ``Selection`` () = + let info = + Checker.getCompletionInfo + """ +let preSelectedItem = 1 +let r = (*MarkerPreSelectedItem*)pre{caret}""" + + assertHasItemWithNames [ "preSelectedItem" ] info + +[] +let ``CompListInDiffFileTypes`` () = + let sigInfo = + Checker.getCompletionInfoOfSignatureFile + """ +val x:int = 1 +x.{caret}""" + + Assert.Equal(0, sigInfo.Items.Length) + + let info = + Checker.getCompletionInfo + """ +let i = 1 +i.{caret}""" + + assertHasItemWithNames [ "CompareTo"; "Equals" ] info + +[] +let ``Keywords.Let`` () = + let info = Checker.getCompletionInfo "let.{caret} a = 1" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Expression.InString`` () = + let info = Checker.getCompletionInfo """let x = "System.Console.{caret}" """ + + Assert.Equal(0, info.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs new file mode 100644 index 00000000000..a224ef10cab --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs @@ -0,0 +1,43 @@ +module FSharp.Compiler.Service.Tests.CompletionLiteralsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Literal.809979`` () = + let info = + Checker.getCompletionInfo """let value=uint64.{caret}""" + + assertHasNoItemsWithNames [ "Parse" ] info + +[] +let ``CharLiteral`` () = + let info = + Checker.getCompletionInfo + """let x = "foo" +let x' = "bar" +x'.{caret}""" + + assertHasItemWithNames [ "CompareTo"; "GetHashCode" ] info + +[] +let ``Literal.Float`` () = + let info = + Checker.getCompletionInfo """let myfloat = (42.0).{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info + +[] +let ``Literal.String`` () = + let info = + Checker.getCompletionInfo """let name = "foo".{caret}""" + + assertHasItemWithNames [ "Chars"; "Clone" ] info + +[] +let ``Literal.Int`` () = + let info = + Checker.getCompletionInfo """let typeint = (10).{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs new file mode 100644 index 00000000000..baee76af18a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs @@ -0,0 +1,361 @@ +module FSharp.Compiler.Service.Tests.CompletionMembersTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +let globalMemberCases: obj[] seq = + [ [| "Basic"; "\nlet x = 1\nx.{caret}" |] + [| "EndingWithTick"; "\nlet x' = 1\nx'.{caret}" |] + [| "PartialMember2"; "\nlet x = 1\nx.{caret}CompareT" |] + [| "ContainingTick"; "\nlet x'y = 1\nx'y.{caret}" |] + [| "PartialMember1"; "\nlet x = 1\nx.CompareT{caret}" |] ] + +[] +let ``GlobalMember completion lists CompareTo and GetHashCode`` (caseName: string) (source: string) = + assertHasItemWithNames [ "CompareTo"; "GetHashCode" ] (Checker.getCompletionInfo source) + +[] +[] +[")>] +[] +[] +[] +[] +let ``AdjacentToDot positive`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +[] +[{caret}")>] +[] +[] +[] +[] +[] +let ``AdjacentToDot negative`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "BackgroundColor" ] info + +[] +let ``CtrlSpaceCompletion.Bug130670.Case1`` () = + let info = Checker.getCompletionInfo "let i = async.Return(4){caret}" + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "GetType" ] info + +[] +let ``InString`` () = + let info = Checker.getCompletionInfo " // System.C{caret} " + + Assert.Equal(0, info.Items.Length) + +[] +let ``EmptyFile.Dot.Bug1115`` () = + let info = Checker.getCompletionInfo ".{caret}" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Project.FsFileWithBuildAction`` () = + let info = + Checker.getCompletionInfo + """ +let i = 4 +let r = i.{caret}ToString() +let x = File1.bob""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``DotOff.String`` () = + let info = + Checker.getCompletionInfo + """ +"x".{caret} (*marker*) +""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``Bug243082.DotAfterNewBreaksCompletion2`` () = + let info = + Checker.getCompletionInfo + """ +let s = 1 +s.{caret} +new System.""" + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +let ``NotShowInfo.LetBinding.Bug3602`` () = + let info = + Checker.getCompletionInfo + """ +let s.{caret} = "Hello world" + ()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``HandleInlineComments1`` () = + let info = + Checker.getCompletionInfo "let rrr = System (* boo! *) .{caret} Int32 . MaxValue" + + assertHasItemWithNames [ "Int32" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``HandleInlineComments2`` () = + let info = + Checker.getCompletionInfo "let rrr = System (* boo! *) . Int32 .{caret} MaxValue" + + assertHasItemWithNames [ "MaxValue" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Expression.MultiLine.Bug66705`` () = + let info = + Checker.getCompletionInfo + """ +let x = 4 +let y = x.GetType() + .{caret}ToString()""" + + assertHasItemWithNames [ "ToString" ] info + +[] +[] +[] +[] +[] +let ``IncompleteStatement`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``WithNonExistentDll`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| @"-r:..\bar\nonexistent.dll" |] + FSharpCodeCompletionOptions.Default + "(*marker*) {caret} " + + assertHasItemWithNames [ "System"; "Array2D" ] info + assertHasNoItemsWithNames [ "Int32" ] info + +[] +let ``FlagsAndSettings.Bug1969`` () = + let info = + Checker.getCompletionInfo + """ +let y = System.Deployment.Application.{caret} +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``OfSystemWindows`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:System.Windows.Forms.dll" |] + FSharpCodeCompletionOptions.Default + "let y=new System.Windows.{caret}" + + Assert.Equal(3, info.Items.Length) + +[] +let ``Editor.WithoutContext.Bug986`` () = + let info = Checker.getCompletionInfo "{caret}" + + assertHasNoItemsWithNames [ "IChapteredRowset"; "ICorRuntimeHost" ] info + +[] +let ``LetBind.TopLevel.Bug1650`` () = + let info = Checker.getCompletionInfo "let x = {caret}" + + assertHasItemWithNames [ "System" ] info + +[] +let ``PrimTypeAndFunc`` () = + let info1 = + Checker.getCompletionInfo + """ +System.Int32.{caret} +int. """ + + assertHasItemWithNames [ "MinValue" ] info1 + + let info2 = + Checker.getCompletionInfo + """ +System.Int32. +int.{caret} """ + + assertHasNoItemsWithNames [ "MinValue" ] info2 + +[] +let ``ThirdLevelOfDotting`` () = + let info = Checker.getCompletionInfo "let x = System.Console.Wr{caret}" + + assertHasItemWithNames [ "BackgroundColor"; "CancelKeyPress" ] info + + for item in info.Items do + match item.NameInCode with + | "BackgroundColor" -> Assert.Equal(CompletionItemKind.Property, item.Kind) + | "CancelKeyEvent" -> Assert.Equal(CompletionItemKind.Event, item.Kind) + | _ -> () + +[] +let ``Expression.WithoutPreDefinedMethods`` () = + let info = + Checker.getCompletionInfo + """ + let x = F{caret}""" + + assertHasNoItemsWithNames [ "FSharpDelegateEvent"; "PrivateMethod"; "PrivateType" ] info + +[] +let ``CaseInsensitive.MapMethod`` () = + let info = + Checker.getCompletionInfo + """ + List.MaP{caret} + """ + + assertHasItemWithNames [ "map" ] info + +[] +let ``SimpleTypes.SystemTime`` () = + let info = + Checker.getCompletionInfo + """ + let typestruct = System.DateTime.Now + typestruct.{caret}""" + + assertHasItemWithNames [ "AddDays"; "Date" ] info + +[] +[] +[] +[] +[] +let ``MacroDirectives`` (source: string) = + let info = Checker.getCompletionInfo source + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.This`` () = + let info = + Checker.getCompletionInfo + """ + type Type1 = + member this.{caret}.Foo () = 3""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Regression4702.SystemWord`` () = + let info = Checker.getCompletionInfo "System.{caret}" + + assertHasItemWithNames [ "Console"; "Byte"; "ArgumentException" ] info + +[] +let ``ExpressionDotting.Regression.Bug3709`` () = + let info = + Checker.getCompletionInfo + """ + let foo = "" + let foo = foo.E{caret}n "a" """ + + assertHasItemWithNames [ "EndsWith" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test2`` () = + let info = + Checker.getCompletionInfo + """ + type T() = + member _.M() = [|1..2|] + type R = { P : T } + // dotting through an F# record field + let r = { P = T() } + r.P.M().{caret} """ + + assertHasItemWithNames [ "Clone" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test3`` () = + let info = + Checker.getCompletionInfo + """ + type R = { P : System.Reflection.InterfaceMapping } + // Dotting through an F# record field and an IL record field + // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib + let r = { P = Unchecked.defaultof } + r.P.{caret}""" + + assertHasItemWithNames [ "InterfaceMethods" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test4`` () = + let info = + Checker.getCompletionInfo + """ + type R = { P : System.Reflection.InterfaceMapping } + // Dotting through an F# record field and an IL record field + // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib + let f() = { P = Unchecked.defaultof } + f().P.{caret}""" + + assertHasItemWithNames [ "InterfaceMethods" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test5`` () = + let info = + Checker.getCompletionInfo + """ + type R = { P : System.Reflection.InterfaceMapping } + // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib + let f() = { P = Unchecked.defaultof } + f().P.InterfaceMethods.{caret}""" + + assertHasItemWithNames [ "GetEnumerator" ] info + +[] +[] +[] +let ``ExpressionDotting.Regression.Bug187799.Test6`` (markedSource: string, expected: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ expected ] info + +[] +let ``Fsx.Bug2530FsiObject`` () = + let info = Checker.getCompletionInfo "fsi.{caret}" + + assertHasItemWithNames [ "CommandLineArgs" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs new file mode 100644 index 00000000000..d949c13606e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs @@ -0,0 +1,102 @@ +module FSharp.Compiler.Service.Tests.CompletionModulesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``String.BeforeIncompleteModuleDefinition.Bug2385`` () = + let info = + Checker.getCompletionInfo + """let s = "hello".{caret} +module Timer =""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``Identifier.DefineByVal.InFsiFile.Bug882304_1`` () = + let info = + Checker.getCompletionInfoOfSignatureFile + """module BasicTest +val z:int = 1 +z.{caret}""" + + assertHasNoItemsWithNames [ "Equals" ] info + +[] +let ``ShowSetAsModuleAndType`` () = + let info = Checker.getCompletionInfo "let s = Set{caret}" + + let tip = flattenItemDescription (findCompletionItem "Set" info).Description + Assert.Contains("module Set", tip) + Assert.Contains("type Set", tip) + +[] +let ``Expression.WithPreDefinedMethods`` () = + let info = + Checker.getCompletionInfo + """ + module Module1 = + let private PrivateField = 1 + let private PrivateMethod x = + x+1 + type private PrivateType() = + member this.mem = 1 + let a = {caret} + + let b = 23 + """ + + assertHasItemWithNames [ "PrivateField"; "PrivateMethod"; "PrivateType" ] info + +[] +let ``Identifier.AsModule`` () = + let info = Checker.getCompletionInfo "module Module1.{caret}" + + Assert.Equal(0, info.Items.Length) + +[] +let ``TypeAbbreviation.Positive`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + Microsoft.FSharp.Core.{caret}""" + + assertHasItemWithNames [ "int16"; "int32"; "int64" ] info + +[] +let ``TypeAbbreviation.Negative`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + Microsoft.FSharp.Core.{caret}""" + + assertHasNoItemsWithNames [ "Int16"; "Int32"; "Int64" ] info + +[] +let ``Verify no completion on dot after module definition`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest.{caret} + + let foo x = x + let bar = 1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Verify no completion after module definition`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest {caret} + + let foo x = x + let bar = 1""" + + Assert.Equal(0, info.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs new file mode 100644 index 00000000000..0582e8a578b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs @@ -0,0 +1,61 @@ +module FSharp.Compiler.Service.Tests.CompletionMutabilityTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AdjacentToDot_20`` () = + let info = Checker.getCompletionInfo "System.Console.{caret}()<-" + + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +let ``AdjacentToDot_20_Negative`` () = + let info = Checker.getCompletionInfo "System.Console.()<-{caret}" + + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "BackgroundColor" ] info + +let private obsoletePreamble = """[] +module ObsoleteTop = + let T = "T" +module Module = + [] + module ObsoleteM = + let A = "A" + [] + module ObsoleteNested = + let C = "C" + [] + type ObsoleteT = + static member B = "B" + let Other = 0 +let mutable level = "" + +""" + +let obsoleteCases: obj[] seq = + [ + [| box "level <- O{caret}"; box [ "None" ]; box [ "ObsoleteTop"; "Chars" ] |] + [| box "level <- Module.{caret}"; box [ "Other" ]; box [ "ObsoleteM"; "ObsoleteT"; "Chars" ] |] + [| box "level <- Module.ObsoleteM.{caret}"; box [ "A" ]; box [ "ObsoleteNested"; "Chars" ] |] + [| box "level <- Module.ObsoleteM.ObsoleteNested.{caret}"; box [ "C" ]; box [ "Chars" ] |] + [| box "level <- Module.ObsoleteT.{caret}"; box [ "B" ]; box [ "Chars" ] |] + ] + +[] +let ``Obsolete.completion`` (completionLine: string) (included: string list) (excluded: string list) = + let info = Checker.getCompletionInfo (obsoletePreamble + completionLine) + assertHasItemWithNames included info + assertHasNoItemsWithNames excluded info + +[] +let ``Identifier.InClass.WithoutDef`` () = + let info = + Checker.getCompletionInfo + """ + type Type2 = + val mutable x.{caret} : string""" + + Assert.Equal(0, info.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs new file mode 100644 index 00000000000..cdf9ef3ba73 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs @@ -0,0 +1,25 @@ +module FSharp.Compiler.Service.Tests.CompletionMutuallyRecursiveTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ProtectedMembers.SelfOrDerivedClass`` () = + let info1 = + Checker.getCompletionInfo + """type T() = + inherit exn() + member this.Run(x : T) = x.{caret}""" + + assertHasItemWithNames [ "Message"; "HResult" ] info1 + + let info2 = + Checker.getCompletionInfo + """type T() = + inherit exn() + member this.Run(x : Z) = x.{caret} +and Z() = + inherit T()""" + + assertHasItemWithNames [ "Message"; "HResult" ] info2 diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs new file mode 100644 index 00000000000..23da9f8e443 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs @@ -0,0 +1,99 @@ +module FSharp.Compiler.Service.Tests.CompletionNamespacesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``List.AfterAddLinqNamespace.Bug3754`` () = + let info = + Checker.getCompletionInfo + """open System.Xml.Linq +List.{caret}""" + + assertHasItemWithNames [ "map"; "filter" ] info + +[] +let ``Global`` () = + let info = Checker.getCompletionInfo "global.{caret}" + + assertHasItemWithNames [ "System"; "Microsoft" ] info + +[] +let ``Identifier.NonDottedNamespace.Bug1347`` () = + let info = + Checker.getCompletionInfo + """open System +let x = Mic{caret} +let p7 = + let sieve limit = + let isPrime = Array.create (limit+1) true + for n in""" + + assertHasItemWithNames [ "Microsoft" ] info + +[] +let ``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case2`` () = + let info = Checker.getCompletionInfo "open Microsoft.FSharp.Collections.Array.{caret}" + + assertHasItemWithNames [ "Parallel" ] info + assertHasNoItemsWithNames [ "map" ] info + +[] +let ``AtNamespaceDot`` () = + let info = Checker.getCompletionInfo "let y=new System.{caret}String()" + + assertHasItemWithNames [ "String"; "Console" ] info + +[] +let ``SystemNamespace`` () = + let info = Checker.getCompletionInfo "let y = System.{caret}" + + assertHasItemWithNames [ "Action"; "Collections" ] info + + assertItemGlyph "Action" FSharpGlyph.Delegate info + assertItemGlyph "Collections" FSharpGlyph.NameSpace info + +[] +let ``WithoutOpenNamespace`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility +let x = S{caret}""" + + assertHasNoItemsWithNames [ "Single" ] info + +[] +let ``Namespace.System`` () = + let info = + Checker.getCompletionInfo + """ +// Test '.' after System +open System.{caret} +let str = "a string" +// Test '.' after str +let _ = str(*usage*)""" + + assertHasItemWithNames [ "IO"; "Collections" ] info + +[] +let ``Identifier.AsNamespace`` () = + let info = Checker.getCompletionInfo "namespace Namespace1.{caret}" + + Assert.Equal(0, info.Items.Length) + +[] +let ``ReopenNamespace.Module`` () = + let info = + Checker.getCompletionInfo + """ +namespace A +module Test = + let foo n = n + 1 +namespace B +open A +open A +Test.{caret}""" + + assertHasItemWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs new file mode 100644 index 00000000000..2594cc909ed --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs @@ -0,0 +1,27 @@ +module FSharp.Compiler.Service.Tests.CompletionObjectExpressionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ObjInstance.AnonymousClass.MethodsDefInInterface`` () = + let info = + Checker.getCompletionInfo + """ + type IFoo = + abstract DoStuff : unit -> string + abstract DoStuff2 : int * int -> string -> string + // Implement an interface in a class (This is kind of lame if you don't want to actually declare a class) + type Foo() = + interface IFoo with + member this.DoStuff () = "Return a string" + member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z + // instanceOfIFoo is an instance of an anonymous class which implements IFoo + let instanceOfIFoo = { + new IFoo with + member this.DoStuff () = "Implement IFoo" + member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z + }.{caret}""" + + assertHasItemWithNames [ "DoStuff"; "DoStuff2" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs new file mode 100644 index 00000000000..b8fd3c661d9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs @@ -0,0 +1,148 @@ +module FSharp.Compiler.Service.Tests.CompletionObjectInitializersTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +let private propPlain = """ +type A() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let private propGeneric = """ +type A<'a>() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let private propModule = """ +module M = + type A() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let private propModuleGeneric = """ +module M = + type A<'a, 'b>() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let propertyCases: obj[] seq = + [ + [| box (propPlain + "A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propPlain + "A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "new A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "new A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "new A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propPlain + "new A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + + [| box (propGeneric + "A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propGeneric + "A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + + [| box (propModule + "M.A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "M.A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "M.A(S = 1{caret})"); box ([]: string list); box [ "NonSettableProperty"; "SettableProperty" ] |] + [| box (propModule + "M.A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "new M.A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "new M.A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "new M.A(S = 1{caret})"); box ([]: string list); box [ "NonSettableProperty"; "SettableProperty" ] |] + + [| box (propModuleGeneric + "M.A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "M.A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "M.A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propModuleGeneric + "M.A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>(S = 1{caret})"); box ([]: string list); box [ "NonSettableProperty"; "SettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + ] + +[] +let ``ObjectInitializer.CompletionForProperties`` (source: string) (included: string list) (excluded: string list) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames included info + assertHasNoItemsWithNames excluded info + +let private namedPlain = """ +type A = + static member Run(xyz: int, zyx: string) = 1 +""" + +let private namedGeneric = """ +type A = + static member Run<'T>(xyz: 'T, zyx: string) = 1 +""" + +let namedParamCases: obj[] seq = + [ + [| box (namedPlain + "A.Run({caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedPlain + "A.Run(x{caret} = 1)"); box [ "xyz" ] |] + [| box (namedPlain + "A.Run(x = 1,{caret})"); box [ "xyz"; "zyx" ] |] + + [| box (namedGeneric + "A.Run({caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedGeneric + "A.Run(x{caret} = 1)"); box [ "xyz" ] |] + [| box (namedGeneric + "A.Run(x = 1,{caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedGeneric + "A.Run<_>({caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedGeneric + "A.Run<_>(x{caret} = 1)"); box [ "xyz" ] |] + [| box (namedGeneric + "A.Run<_>(x = 1,{caret})"); box [ "xyz"; "zyx" ] |] + ] + +[] +let ``ObjectInitializer.CompletionForNamedParameters`` (source: string) (expected: string list) = + assertHasItemWithNames expected (Checker.getCompletionInfo source) + +let private settablePlain = """ +type A0() = member val Settable0 = 1 with get,set +type A() = + member val Settable = 1 with get,set + member val NonSettable = 1 + static member Run(): A0 = Unchecked.defaultof<_> + static member Run(a: string): A = Unchecked.defaultof<_> +""" + +let private settableGeneric = """ +type A0() = member val Settable0 = 1 with get,set +type A() = + member val Settable = 1 with get,set + member val NonSettable = 1 + static member Run<'T>(): A0 = Unchecked.defaultof<_> + static member Run(a: int): A = Unchecked.defaultof<_> +""" + +let settableReturnCases: obj[] seq = + [ + [| box (settablePlain + "A.Run({caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settablePlain + "A.Run(S{caret} = 1)"); box [ "Settable"; "Settable0" ] |] + [| box (settablePlain + "A.Run(S = 1,{caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settablePlain + "A.Run(Settable = 1,{caret})"); box [ "Settable0" ] |] + + [| box (settableGeneric + "A.Run({caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run(S{caret} = 1)"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run(S = 1,{caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run(Settable = 1,{caret})"); box [ "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>({caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>(S{caret} = 1)"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>(S = 1,{caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>(Settable = 1,{caret})"); box [ "Settable0" ] |] + ] + +[] +let ``ObjectInitializer.CompletionForSettablePropertiesInReturnValue`` (source: string) (included: string list) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames included info + assertHasNoItemsWithNames [ "NonSettable" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs new file mode 100644 index 00000000000..6ed30db0888 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs @@ -0,0 +1,304 @@ +module FSharp.Compiler.Service.Tests.CompletionOpenDirectivesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``LambdaOverloads.Completion`` () = + let info = + Checker.getCompletionInfo + """open System.Linq +let _ = [""].Sum(fun x -> x.Len{caret})""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Duplicates.Bug4103a`` () = + let info = Checker.getCompletionInfo "open Microsoft.FSharp.Quotations\nExpr.{caret}" + + assertItemDescriptionContainsExactlyOnce "WhileLoop" "WhileLoop" info + +[] +let ``StandardTypes.Bug4403`` () = + let info = + Checker.getCompletionInfo + """open System +let x={caret}""" + + assertHasItemWithNames [ "int8"; "int16"; "int32"; "string"; "SByte"; "Int16"; "Int32"; "String" ] info + +[] +let ``NameSpace.InFsiFile.Bug882304_2`` () = + let info = + Checker.getCompletionInfoOfSignatureFile + """module BasicTest +open System.{caret}""" + + assertHasItemWithNames [ "Action"; "Activator"; "Collections"; "IConvertible" ] info + +[] +let ``Duplicates.Bug4103c`` () = + let info = + Checker.getCompletionInfo + """open System.IO +open System.IO +File.{caret}""" + + let expectedOverloads = + typeof.GetMethods() + |> Array.filter (fun m -> m.Name = "Open") + |> Array.length + + assertItemDescriptionOccurrences expectedOverloads "Open" "File.Open" info + +[] +let ``Duplicates.Bug2094`` () = + let info = + Checker.getCompletionInfo + """open Microsoft.FSharp.Control +let b = MailboxProcessor.{caret}""" + + assertItemDescriptionOccurrences 2 "Start" "Start" info + +[] +let ``Identifier.String.Positive`` () = + let info = + Checker.getCompletionInfo + """ + open System + let str = "a string" + // Test '.' after str + let _ = str.{caret} + """ + + assertHasItemWithNames [ "Chars"; "ToString"; "Length"; "GetHashCode" ] info + +[] +let ``Identifier.String.Negative`` () = + let info = + Checker.getCompletionInfo + """ + open System + let str = "a string" + // Test '.' after str + let _ = str.{caret} + """ + + assertHasNoItemsWithNames [ "Parse"; "op_Addition"; "op_Subtraction" ] info + +[] +let ``ImportStatement.System.ImportDirectly`` () = + let info = + Checker.getCompletionInfo + """ + open System.{caret} + open IO = System(*Mimportstatement2*)""" + + assertHasItemWithNames [ "Collections" ] info + +[] +let ``ImportStatement.System.ImportAsIdentifier`` () = + let info = + Checker.getCompletionInfo + """ + open System(*Mimportstatement1*) + open IO = System.{caret}""" + + assertHasItemWithNames [ "IO" ] info + +[] +let ``ObjInstance.ExtensionMethods.WithoutDef.Negative`` () = + let info = + Checker.getCompletionInfo + """ + open System + let rnd = new System.Random() + rnd.{caret}""" + + assertHasNoItemsWithNames [ "NextDice"; "DiceValue" ] info + +[] +let ``Expression.InComment`` () = + let info = + Checker.getCompletionInfo + """ + //open System + //open IO = System.{caret}""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``ShortFormSeqExpr.Bug229610`` () = + let info = + Checker.getCompletionInfo + """module test + +open System.Text.RegularExpressions + +let getLinks (txt: string) = + [ for m in Regex.Matches(txt, "pattern") -> m.Groups.Item(1).{caret} ]""" + + assertHasItemWithNames [ "Value" ] info + +[] +let ``ReOpenNameSpace.SystemLibrary`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open System.IO + open System.IO + + File.{caret} + """ + + assertHasItemWithNames [ "Open" ] info + +[] +let ``ReOpenNameSpace.MailboxProcessor`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open Microsoft.FSharp.Control + open Microsoft.FSharp.Control + let counter = + MailboxProcessor.{caret}""" + + assertHasItemWithNames [ "Start" ] info + +[] +let ``Seq.NearTheEndOfFile`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open Microsoft.FSharp.Math + + let trianglenumbers = Seq.init_infinite (fun i -> let i = BigInt(i) in i * (i+1I) / 2I) + + (trianglenumbers |> Seq.{caret})""" + + assertHasItemWithNames [ "cache"; "find" ] info + +[] +[] +[")>] +let ``Regression3754.TypeOfListForward`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3754 + // tupe forwarder bug? intellisense bug? + + open System.IO + open System.Xml + open System.Xml.Linq + let xmlStr = @" Blah Blah " + let xns = XNamespace.op_Implicit "" + let a = xns + "a" + let reader = new StringReader(xmlStr) + let xdoc = XDocument.Load(reader) + let aElements = [for x in xdoc.Root.Elements() do + if x.Name = a then + yield x] + let href = xns + "href" + aElements |> List.{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +let ``NonApplicableExtensionMembersDoNotAppear.Bug40379`` () = + let source (decl: string) = + sprintf + """open System.Xml.Linq +type MyType() = + static member Foo(actual: XElement) = actual.Name + member public this.Bar() = + let actual: %s = failwith "" + actual.{caret}""" + decl + + let info1 = Checker.getCompletionInfo (source "int[]") + assertHasNoItemsWithNames [ "Ancestors"; "AncestorsAndSelf" ] info1 + + let info2 = Checker.getCompletionInfo (source "XNode[]") + assertHasItemWithNames [ "Ancestors" ] info2 + assertHasNoItemsWithNames [ "AncestorsAndSelf" ] info2 + + let info3 = Checker.getCompletionInfo (source "XElement[]") + assertHasItemWithNames [ "Ancestors"; "AncestorsAndSelf" ] info3 + +[] +let ``Verify no completion in hash directives`` () = + let info = + Checker.getCompletionInfo + """ + #r {caret} + + let foo x = x + let bar = 1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Fsx.HashLoad.Conditionals`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "--define:INTERACTIVE" |] + FSharpCodeCompletionOptions.Default + """module InDifferentFS = +#if INTERACTIVE + let x = 1 +#else + let y = 2 +#endif +#if RELEASE + let A = 3 +#else + let B = 4 +#endif + +InDifferentFS.{caret}""" + + assertHasItemWithNames [ "x"; "B" ] info + assertHasNoItemsWithNames [ "y"; "A" ] info + Assert.Equal(2, info.Items.Length) + +[] +let ``Fsx.BugAllowExplicitReferenceToMsCorlib`` () = + let serviceDll = typeof.Assembly.Location + + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| sprintf "-r:%s" serviceDll |] + FSharpCodeCompletionOptions.Default + """#r "mscorlib" +open FSharp.Compiler.Interactive.Shell.Settings +fsi.{caret}""" + + assertHasItemWithNames [ "CommandLineArgs" ] info + +[] +let ``Fsx.HashReferenceAgainstStrongName`` () = + let source = + sprintf + "#reference \"System.Core, Version=%s, Culture=neutral, PublicKeyToken=b77a5c561934e089\"\nopen System.{caret}" + (System.Environment.Version.ToString()) + + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "Linq" ] info + +[] +let ``Fsx.ShouldBeAbleToReference30Assemblies.Bug2050`` () = + let info = + Checker.getCompletionInfo + """#r "System.Core.dll" +open System.{caret}""" + + assertHasItemWithNames [ "Linq" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs new file mode 100644 index 00000000000..396ab1a25ca --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs @@ -0,0 +1,59 @@ +module FSharp.Compiler.Service.Tests.CompletionOperatorsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AdjacentToDot_01`` () = + let info = Checker.getCompletionInfo "System.Console.{caret}." + + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +let ``RangeOperator.IncorrectUsage`` () = + let info2Dots = Checker.getCompletionInfo "..{caret}" + Assert.Equal(0, info2Dots.Items.Length) + + let info3Dots = Checker.getCompletionInfo "...{caret}" + Assert.Equal(0, info3Dots.Items.Length) + +[] +let ``RangeOperator.CorrectUsage`` () = + let singleLine = Checker.getCompletionInfo "let _ = [1..{caret}]" + assertHasItemWithNames [ "abs" ] singleLine + + let multiLine = + Checker.getCompletionInfo + """[ + 1 + ..{caret} +]""" + + assertHasItemWithNames [ "abs" ] multiLine + +[] +let ``Array.AfterOperator...Bug65732_A`` () = + let info = Checker.getCompletionInfo "let r = [1 .. System.{caret}Int32.MaxValue]" + + assertHasItemWithNames [ "Int32" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +[] +[] +[] +[] +[] +let ``Array.AfterOperator...Bug65732_B_C_D`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Dot.AfterOperator.Bug69159`` () = + let info = Checker.getCompletionInfo "let x1 = [|0..1..10|].{caret}" + + assertHasItemWithNames [ "Length" ] info + assertHasNoItemsWithNames [ "abs" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs new file mode 100644 index 00000000000..4aaf1724c5a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs @@ -0,0 +1,281 @@ +module FSharp.Compiler.Service.Tests.CompletionPatternMatchingTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``TupledArgsInLambda.Completion.Bug312557_2`` () = + let assertOffersTupleArgs (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "aaa"; "bbb" ] info + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b{caret} a + printfn "%d%d" a b ) """ + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b a + printfn "%d%d" a{caret} b ) """ + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b a{caret} + printfn "%d%d" a b ) """ + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b a + printfn "%d%d" a b{caret} ) """ + +[] +let ``DotCompletionInPatternsPartOfLambda`` () = + let info = Checker.getCompletionInfo "let _ = fun x .{caret} -> x + 1" + Assert.Equal(0, info.Items.Length) + +[] +let ``DotCompletionInPatterns`` () = + let assertEmpty (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + Assert.Equal(0, info.Items.Length) + + assertEmpty "let (x, y .{caret}) = 1, 2" + assertEmpty "let run (o : obj) = match o with | :? int as i .{caret} -> 1 | _ -> 0" + assertEmpty "let (``x.y``, ``y.z`` .{caret}) = 1, true" + assertEmpty "let ``x`` .{caret} = 1" + +[] +let ``MatchStatement.WhenClause.Bug2519`` () = + let info = + Checker.getCompletionInfo + """type DU = X of int +let timefilter pkt = + match pkt with + | X(hdr) when (*aaa*)hdr.{caret} + | _ -> ()""" + + assertHasItemWithNames [ "CompareTo"; "GetHashCode" ] info + +[] +let ``Bug229433.AfterMismatchedParensCauseWeirdParseTreeAndExceptionDuringTypecheck`` () = + let info = + Checker.getCompletionInfo + """ + type T() = + member this.Bar() = () + member val X = "foo" with get,set + static member Id(x) = x + [1] + |> Seq.iter (fun x -> + let user = x + ["foo"] + |> List.iter (fun m -> + let xyz = new T() + xyz.X <- null + T.Id((*here*)xyz.{caret} // no intellisense here after . + ) + printfn "" + ) """ + + assertHasItemWithNames [ "Bar"; "X" ] info + +[] +let ``Identifer.InMatchStatement.Bug72595`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + let someValue = "abc" + member _.M() = + let x = 1 + match someValue.{caret} with + let x = 1 + match 1 with + | _ -> 2 + type D() = + member x.P = 1 + [] + do() + """ + + assertHasItemWithNames [ "Chars" ] info + +[] +[ Array.mapi (fun i c ->""")>] +[ Array.mapi (fun i c -> +let p5 = 1""")>] +let ``LambdaExpression.WithoutClosing.Bug1346`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "Length" ] info + +[] +let ``IncompleteStatement.Match_A`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +let test2 = match (x).{caret}""" + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``IncompleteStatement.Match_C`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +let test2 = match (x).{caret} +let y = 2""" + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``WithinMatchClause.Bug1603`` () = + let info = + Checker.getCompletionInfo + """let rec f l = + match l with + | [] -> + let xx = System.DateTime.Now + let y = xx.{caret} + | x :: xs -> f xs""" + + assertHasItemWithNames [ "AddMilliseconds" ] info + +[] +let ``MatchStatement.Clause.AfterLetBinds.Bug1603`` () = + let info = + Checker.getCompletionInfo + """let rec f l = + match l with + | [] -> + let xx = System.DateTime.Now + let y = xx + | x :: xs -> f xs.{caret}""" + + assertHasItemWithNames [ "Head"; "Tail" ] info + + let headTail = + info.Items |> Array.filter (fun i -> i.NameInCode = "Head" || i.NameInCode = "Tail") + + if headTail.Length <> 2 then + failwithf + "Expected exactly 2 items named Head/Tail but found %d: [%s]" + headTail.Length + (headTail |> Array.map _.NameInCode |> String.concat ", ") + + for item in headTail do + if item.Glyph <> FSharpGlyph.Property then + failwithf "Item %A has glyph %A but expected Property" item.NameInCode item.Glyph + +[] +let ``BestMatch.Bug4320a`` () = + let info = Checker.getCompletionInfo " let x = System.{caret}" + assertHasItemWithNames [ "GC"; "GCCollectionMode" ] info + assertPrefixIsNotUnique "G" false info + assertPrefixIsUnique "GCC" false info + +[] +let ``BestMatch.Bug4320b`` () = + let info = Checker.getCompletionInfo " let x = List.{caret}" + assertHasItemWithNames [ "empty" ] info + assertPrefixIsNotUnique "e" false info + assertPrefixIsUnique "em" false info + +[] +let ``BestMatch.Bug5131`` () = + let info = Checker.getCompletionInfo "System.Environment.{caret}" + assertHasItemWithNames [ "OSVersion" ] info + assertPrefixIsUnique "o" true info + +[] +let ``Identifier.InMatchStatement`` () = + let info = + Checker.getCompletionInfo + """ +let x = 1 +match x.{caret} with + |1 -> 1*1 + |2 -> 2*2 +""" + + assertHasItemWithNames [ "ToString"; "Equals" ] info + +[] +let ``Identifier.InMatchClause`` () = + let info = + Checker.getCompletionInfo + """ +let rec f l = + match l with + | [] -> + let xx = System.DateTime.Now + let y = xx.{caret} + () + | x :: xs -> f xs +""" + + assertHasItemWithNames [ "Add"; "Date" ] info + +[] +let ``Keywords.Match`` () = + let info = + Checker.getCompletionInfo + """ + match.{caret} a with + | pattern -> exp""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.InMatch.UnderScore`` () = + let info = + Checker.getCompletionInfo + """ + let x = 1 + match x with + |1 -> 1*2 + |2 -> 2*2 + |_.{caret} -> 0 """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.InFunctionMatch`` () = + let info = + Checker.getCompletionInfo + """ + let f5 = function + | 1.{caret} -> printfn "1" + | 2 -> printfn "2" """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``Expression.InMatchWhenClause`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + type DU = X of int + let timefilter pkt = + match pkt with + | X(hdr) when hdr.{caret} -> () + | _ -> () + """ + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs new file mode 100644 index 00000000000..56ffcebebf1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs @@ -0,0 +1,70 @@ +module FSharp.Compiler.Service.Tests.CompletionPrintfFormatTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``TupledArgsInLambda.Completion.Bug312557_1`` () = + let info = + Checker.getCompletionInfo + """[(1,2);(1,2);(1,2)] +|> Seq.iter (fun (xxx,yyy) -> printfn "%d" {caret} + printfn "%d" 1)""" + + assertHasItemWithNames [ "xxx"; "yyy" ] info + +[] +let ``CtrlSpaceInWhiteSpace.Bug133112`` () = + let info = + Checker.getCompletionInfo + """ + type Foo = + static member A = 1 + static member B = 2 + printfn "%d %d" Foo.A {caret} """ + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "A"; "B" ] info + +[] +let ``BY_DESIGN.ExplicitlyCloseTheParens.Bug73940`` () = + let info = + Checker.getCompletionInfo + """ + let g lam = + lam true |> printfn "%b" + sprintf "%s" + let r = + ["1"] + |> List.map (fun s -> s.{caret} ) // user types close paren here to avoid paren mismatch + |> g // regardless of whatever is down here now, it won't affect the type of 's' above + """ + + assertHasItemWithNames [ "Chars" ] info + +[] +let ``BY_DESIGN.MismatchedParenthesesAreHardToRecoverFromAndHereIsWhy.Bug73940`` () = + let info = + Checker.getCompletionInfo + """ + let g lam = + lam true |> printfn "%b" + sprintf "%s" + let r = + ["1"] + |> List.map (fun s -> s.{caret} // it looks like s is a string here, but it's not! + |> g // parser recovers as though there is a right-paren here + """ + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "Chars" ] info + +[] +let ``Identifier.AfterParenthesis.Bug6484_2`` () = + let info = + Checker.getCompletionInfo + """for x = 1 to 10 do + printfn "%s" (x.{caret} """ + + assertHasItemWithNames [ "CompareTo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs new file mode 100644 index 00000000000..3bfe01ba304 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs @@ -0,0 +1,337 @@ +module FSharp.Compiler.Service.Tests.CompletionPropertiesTests + +open FSharp.Test +open Xunit + +[] +let ``ObsoleteProperties.6377_1`` () = + let info = + Checker.getCompletionInfo + """type StandIn() = + [] + static member val SecurityEnabled = false with get, set + static member GetStandardSandbox() = 0 +StandIn.{caret}""" + + assertHasItemWithNames [ "GetStandardSandbox" ] info + assertHasNoItemsWithNames [ "get_SecurityEnabled"; "set_SecurityEnabled" ] info + +[] +let ``ObsoleteProperties.6377_2`` () = + let info = Checker.getCompletionInfo "System.Threading.Thread.CurrentThread.{caret}" + + assertHasItemWithNames [ "CurrentCulture" ] info + assertHasNoItemsWithNames [ "get_ApartmentState"; "set_ApartmentState" ] info + +[] +let ``Class.Property.Bug69150_A`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = (new ClassType(23)).{caret}Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Class.Property.Bug69150_B`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = ClassType(23).{caret}Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Class.Property.Bug69150_C`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let f x = new ClassType(x) +let z = f(23).{caret}Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Class.Property.Bug69150_D`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = ClassType(23).V{caret}alue""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "VolatileFieldAttribute" ] info + +[] +let ``Class.Property.Bug69150_E`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = ClassType(23) . {caret} Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "VolatileFieldAttribute" ] info + +[] +let ``AssignmentToProperty.Bug231283`` () = + let info = + Checker.getCompletionInfo + """ + type Foo() = + member val Bar = 0 with get,set + let f = new Foo() + f.Bar <- + let xyz = 42 {caret}(*Mark*) + xyz """ + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "Bar" ] info + +[] +let ``Bug130733.LongIdSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let c = C() + c.X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.LongIdSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let c = C() + c.{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.ExprDotSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let f(x) = C() + f(0).X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.ExprDotSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let f(x) = C() + f(0).{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.LongIdSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let c = C() + c.CC.X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.LongIdSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let c = C() + c.CC.{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.ExprDotSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let f(x) = C() + f(0).CC.X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.ExprDotSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let f(x) = C() + f(0).CC.{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.NamedIndexedPropertyGet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + let str = "foo" + str.Chars(3).{caret}""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``Bug130733.NamedIndexedPropertyGet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + let str = "foo" + str.Chars(3).Co{caret}""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +[] +[] +let ``Bug230533.NamedIndexedPropertySet.CtrlSpace`` (source: string) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames [ "MutableInstanceIndexer" ] info + +[] +let ``Bug230533.ExprDotSet.CtrlSpace.Case1`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + type D() = + member this.CC = new C() + let f(x) = D() + f(0).CC.{caret} <- 42 """ + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug230533.ExprDotSet.CtrlSpace.Case2`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + type D() = + member this.CC with get() = new C() and set(x) = () + let f(x) = D() + f(0).CC.{caret} <- 42 """ + + assertHasItemWithNames [ "XX" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799`` () = + let info = + Checker.getCompletionInfo + """ + type T() = + member _.P with get() = new T() + member _.M() = [|1..2|] + let t = new T() + t.P.M().{caret} """ + + assertHasItemWithNames [ "Clone" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test8`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + static member XXX with get() = 4 and set(x) = () + static member CCC with get() = C() + C.XXX.{caret} <- 42""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``NoInfiniteLoopInProperties`` () = + let info = + Checker.getCompletionInfo + """ + type NodeCollection() = + member _.Add(n: Node) = () + member _.Item with get (index: int) = Node() + and Node() = + member _.Nodes = NodeCollection() + let tn = Node() + tn.Nodes.{caret}""" + + assertHasNoItemsWithNames [ "Nodes" ] info + +[] +let ``Identifier.AsProperty`` () = + let info = + Checker.getCompletionInfo + """ + type Type2 = + member this.Foo.{caret} = 1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``ExpressionPropertyAssignment.Bug217051`` () = + let info = + Checker.getCompletionInfo + """ + type Foo() = + member val Prop = 0 with get, set + Foo().{caret} <- 4 """ + + assertHasItemWithNames [ "Prop" ] info + +[] +let ``ExpressionProperty.Bug234687`` () = + let info = + Checker.getCompletionInfo + """ + open System.Reflection + let x = obj() + let a = x.GetType().Assembly.{caret} + """ + + assertHasItemWithNames [ "CodeBase" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs new file mode 100644 index 00000000000..89024fcde35 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs @@ -0,0 +1,362 @@ +module FSharp.Compiler.Service.Tests.CompletionQueriesTests + +open Xunit + +[] +let ``Query.CompletionInJoinOn`` () = + let info = + Checker.getCompletionInfo + """ +query { + for a in [1] do + join b in [2] on (a.{caret}) + select (a + b) +}""" + + assertHasItemWithNames [ "GetHashCode"; "CompareTo" ] info + +[] +let ``Query.GroupJoin.CompletionInIncorrectJoinRelations`` () = + let info = + Checker.getCompletionInfo + """ +let t = + query { + for x in [1] do + groupJoin y in [""] on (x.{caret} ?=? y.) into g + select 1 }""" + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Query.Join.CompletionInIncorrectJoinRelations`` () = + let info = + Checker.getCompletionInfo + """ +let t = + query { + for x in [1] do + join y in [""] on (x.{caret} ?=? y.) + select 1 }""" + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Query.ForKeywordCanCompleteIntoIdentifier`` () = + let info = + Checker.getCompletionInfo + """ +let form = 42 +let t = + query { + for{caret} + }""" + + assertHasItemWithNames [ "form" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest0`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = si{caret}""" + + assertHasItemWithNames [ "sin" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest0b`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = qu{caret}""" + + assertHasItemWithNames [ "query" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest1`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do sel{caret}""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest1b`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do {caret}""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest2`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do sel{caret} }""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest3`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for xxxxxx in [1;2;3] do xxx{caret}""" + + assertHasItemWithNames [ "xxxxxx" ] info + +[] +[] +[] +let ``QueryExpression.CtrlSpaceSmokeTest3b_3c`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ "xxxxxx" ] info + +[] +let ``QueryExpression.CtrlSpaceSystematic1`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do sel{caret}""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpressions.QueryAndSequenceExpressionWithForYieldLoopSystematic`` () = + let info = + Checker.getCompletionInfo + """ +module Test +let aaaaaa = [| "1" |] +let v = query { for bbbb in [ aaaaaa ] do yield {caret}""" + + assertHasItemWithNames [ "aaaaaa"; "bbbb" ] info + +[] +let ``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnSingleLine`` () = + let info = + Checker.getCompletionInfo + """ +module Test +let abbbbc = [| 1 |] +let aaaaaa = 0 +let x = query { for bbbb in abbbbc do join cccc in abbb{caret}""" + + assertHasItemWithNames [ "abbbbc" ] info + +[] +let ``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnMultipleLine`` () = + let info = + Checker.getCompletionInfo + """ +module Test +let abbbbc = [| 1 |] +let aaaaaa = 0 +let x = query { for bbbb in abbbbc do + join cccc in abbb{caret}""" + + assertHasItemWithNames [ "abbbbc" ] info + +[] +let ``QueryExpression.CtrlSpaceSystematic2`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do {caret}""" + + assertHasItemWithNames [ "select"; "where" ] info + +[] +let ``Query.Auto.InNestedQuery`` () = + let info = + Checker.getCompletionInfo + """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + let maxNumber = query {for x in tuples do ma{caret}} + select n }""" + + assertHasItemWithNames [ "maxBy"; "maxByNullable" ] info + +[] +let ``Query.Auto.OffSetFromPreviousLine`` () = + let info = + Checker.getCompletionInfo + """ +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + gro{caret} + }""" + + assertHasItemWithNames [ "groupBy"; "groupJoin"; "groupValBy" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest1`` () = + let info = + Checker.getCompletionInfo + """ +module Basic +let x2 = query { for x in ["1";"2";"3"] do + select x.{caret}""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest2`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in ["1";"2";"3"] do select x.{caret}""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest0`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = seq { for x in ["1";"2";"3"] do yield x.{caret} }""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest3`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in ["1";"2";"3"] do select x.{caret} }""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSystematic1`` () = + let info = + Checker.getCompletionInfo + """ +module Simple +let x2 = query { for x in ["1";"2";"3"] do + select x.{caret}""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.InsideJoin.Bug204147`` () = + let info = + Checker.getCompletionInfo + """ +module Simple +type T() = + member x.GetCollection() = [1;2;3;4] +let q = + query { + for e in [1..10] do + join b in T().{caret} + select b + }""" + + assertHasItemWithNames [ "GetCollection" ] info + +[] +let ``Query.HasErrors.Bug196230`` () = + let info = + Checker.getCompletionInfo + """ +open DataSource +let products = Products.getProductList() +let sortedProducts = + query { + for p in products do + let x = p.ProductID + "a" + sortBy p.{caret} + select p + }""" + + assertHasItemWithNames [ "ProductID"; "ProductName" ] info + +[] +let ``Query.HasErrors2`` () = + let info = + Checker.getCompletionInfo + """ +open DataSource +let products = Products.getProductList() +let sortedProducts = + query { + for p in products do + orderBy (p.{caret}) + }""" + + assertHasItemWithNames [ "ProductID"; "ProductName" ] info + +[] +let ``Query.ShadowedVariables`` () = + let info = + Checker.getCompletionInfo + """ +open DataSource +let products = Products.getProductList() +let p = 12 +let sortedProducts = + query { + for p in products do + select p.{caret} + }""" + + assertHasItemWithNames [ "Category"; "ProductName" ] info + +[] +let ``Query.InNestedQuery`` () = + let info = + Checker.getCompletionInfo + """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + let maxNumber = query {for x in tuples do maxBy x.{caret}} + select (n, query {for y in numbers do minBy y}) }""" + + assertHasItemWithNames [ "Equals"; "GetType" ] info + +[] +let ``Query.NestedExpressionWithinLamda`` () = + let info = + Checker.getCompletionInfo + """ +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let f (x : string) = () +let foo = + query { + for n in numbers do + let x = 42 |> ignore; numbers |> List.iter( fun n -> f ("1" + "1").{caret}) + skipWhile (n < 30) + }""" + + assertHasItemWithNames [ "Chars"; "Length" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs new file mode 100644 index 00000000000..3e6075a60cc --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs @@ -0,0 +1,50 @@ +module FSharp.Compiler.Service.Tests.CompletionQuotationsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Regression3225.Identifier.InQuotation`` () = + let info = + Checker.getCompletionInfo + """ + let _ = <@ let x = "foo" + x.{caret} @>""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``ReOpenNameSpace.FsharpQuotation`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open Microsoft.FSharp.Quotations + open Microsoft.FSharp.Quotations + Expr.{caret} + """ + + assertHasItemWithNames [ "Value" ] info + +[] +[] +[] +let ``Identifier.InActivePattern`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3223 No intellisense at point + open Microsoft.FSharp.Quotations.Patterns + open Microsoft.FSharp.Quotations.DerivedPatterns + let test1 = <@ 1 + 1 @> + let _ = + match test1 with + | Call(None, methInfo, args) -> + if methInfo.{caret} + """ + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs new file mode 100644 index 00000000000..6fac61968a0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs @@ -0,0 +1,409 @@ +module FSharp.Compiler.Service.Tests.CompletionRecordsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Records.DotCompletion.ConstructingRecords1`` () = + let assertOffers (should: string list) (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames should info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + [ "XX" ] + """type OuterRec = {XX : int; YY : string} +let _ = (* MARKER*) {X{caret}""" + + assertOffers + [ "OuterRec" ] + """type OuterRec = {XX : int; YY : string} +let _ = {XX = 1; (* MARKER*)O{caret}""" + + assertOffers + [ "XX"; "YY" ] + """type OuterRec = {XX : int; YY : string} +let _ = {XX = 1; (* MARKER*)OuterRec.{caret}""" + +[] +let ``Records.DotCompletion.ConstructingRecords2`` () = + let check (should: string list) (shouldNot: string list) (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames should info + assertHasNoItemsWithNames shouldNot info + + let info1 = + Checker.getCompletionInfo + """module Mod = + type Rec = {XX : int; YY : string} +let _ = (* MARKER*){X{caret} }""" + + assertHasNoItemsWithNames [ "XX" ] info1 + + check + [ "XX"; "YY" ] + [ "System" ] + """module Mod = + type Rec = {XX : int; YY : string} +let _ = {(* MARKER*)Mod.{caret} = 1; O""" + + check + [ "XX"; "YY" ] + [ "System" ] + """module Mod = + type Rec = {XX : int; YY : string} +let _ = {(* MARKER*)Mod.Rec.{caret} """ + + check + [ "Mod" ] + [ "XX"; "abs" ] + """module Mod = + type Rec = {XX : int; YY : string} +let _ = (* MARKER*){Mod.XX = 1; {caret} }""" + +[] +let ``Records.CopyOnUpdate`` () = + let assertFields (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "a"; "b" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertFields + """module SomeOtherPath = + type r = { a: int; b : int } +let f1 x = { x with SomeOtherPath.{caret} = 3 }""" + + assertFields + """module SomeOtherPath = + type r = { a: int; b : int } +let f2 x = { x with SomeOtherPath.r.{caret} = 3 }""" + + assertFields + """module SomeOtherPath = + type r = { a: int; b : int } +let f3 (x : SomeOtherPath.r) = { x with {caret}}""" + +[] +let ``Records.CopyOnUpdate.NoFieldsCompletionBeforeWith`` () = + let info = + Checker.getCompletionInfo + """type T = {AAA : int} +let r = {AAA = 5} +let b = {r {caret} with }""" + + assertHasNoItemsWithNames [ "AAA" ] info + +[] +let ``Records.Constructors1`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "field1"; "field2" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + """type X = + val field1: int + val field2: string + new() = { f{caret}}""" + + assertOffers + """type X = + val field1: int + val field2: string + new() = { field1; {caret}}""" + + assertOffers + """type X = + val field1: int + val field2: string + new() = { field1 = 5; {caret}}""" + + assertOffers + """type X = + val field1: int + val field2: string + new() = { field1 = 5; f{caret} }""" + +[] +let ``Records.Constructors2.UnderscoresInNames`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "_field1"; "_field2" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + """type X = + val _field1: int + val _field2: string + new() = { _{caret}}""" + + assertOffers + """type X = + val _field1: int + val _field2: string + new() = { _field1; {caret}}""" + +[] +let ``Records.NestedRecordPatterns`` () = + let info = Checker.getCompletionInfo "[1..({contents = 5}).{caret}]" + assertHasItemWithNames [ "Value"; "contents" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Records.Separators1`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "AAA"; "BBB" ] info + + assertOffers + """type X = { AAA : int; BBB : string} +let r = {AAA = 5 {caret}; }""" + + assertOffers + """type X = { AAA : int; BBB : string} +let r = {AAA = 5 ; } +let b = {r with AAA = 5 {caret}; }""" + +[] +let ``Records.Separators2`` () = + let assertOffers (should: string list) (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames should info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + [ "AAA"; "BBB" ] + """type X = { AAA : int; BBB : string} +let r = + { + AAA = 5; +(*MARKER*) {caret} + }""" + + assertOffers + [ "AAA"; "BBB"; "CCC" ] + """type X = { AAA : int; BBB : string; CCC : int} +let r = + { + AAA = 5; {caret} + CCC = 5 + }""" + +[] +let ``Records.Separators2.OffsideRule`` () = + let info = + Checker.getCompletionInfo + """type X = { AAA : int; BBB : string} +let r = + { + AAA = 5 +(*MARKER*){caret} + }""" + + assertHasItemWithNames [ "AAA"; "BBB" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Records.Inherits`` () = + let info = + Checker.getCompletionInfo + """type A = class end +type B = + inherit A + val f1: int + val f2: int + new() = { inherit A(); {caret}}""" + + assertHasItemWithNames [ "f1"; "f2" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Records.Inherits.AfterInheritNewLine`` () = + let info = + Checker.getCompletionInfo + """type A = class end +type B = + inherit A + val f1: int + val f2: int + new() = { inherit A() + (*M*){caret} + }""" + + assertHasItemWithNames [ "f1"; "f2" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Records.MissingBindings`` () = + let assertOffersR (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "R" ] info + assertHasNoItemsWithNames [ "abs" ] info + + let assertOffersFields (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "AAA"; "BBB" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffersR + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; _;{caret} }""" + + assertOffersR + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; _=;{caret} }""" + + assertOffersFields + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; R.{caret} }""" + + assertOffersFields + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; _; R.{caret} }""" + +[] +let ``Records.WRONG.ErrorsInFirstBinding`` () = + let assertNoFields (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasNoItemsWithNames [ "field1"; "field2" ] info + + assertNoFields + """type X = + val field1: int + val field2: string + new() = { field1 =; {caret}}""" + + assertNoFields + """type X = + val field1: int + val field2: string + new() = { field1 =; f{caret}}""" + +[] +let ``Records.InferByFieldsInPriorMethodArguments`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "Left"; "Top"; "Width"; "Height" ] info + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, (* MARKER*)original.{caret})""" + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, original.Height, (* MARKER*)original.{caret})""" + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, original.Height, original.Width, (* MARKER*)original.{caret})""" + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, original.Height, (* MARKER*)original.{caret}, original.Width)""" + +[] +let ``Expression.RecordPattern`` () = + let info = + Checker.getCompletionInfo + """ + type Rec = + { X : int} + member this.Value = 42 + { X = 1 }.{caret} + """ + + assertHasItemWithNames [ "Value"; "ToString" ] info + +[] +let ``SimpleTypes.Record`` () = + let info = + Checker.getCompletionInfo + """ + type Person = { Name: string; DateOfBirth: System.DateTime } + let typrecord = { Name = "Bill"; DateOfBirth = new System.DateTime(1962,09,02) } + typrecord.{caret}""" + + assertHasItemWithNames [ "DateOfBirth"; "Name" ] info + +[] +let ``LongIdent.Record.AsField`` () = + let info = + Checker.getCompletionInfo + """ + module MyModule = + type person = + { name: string; + dateOfBirth: System.DateTime; } + module MyModule2 = + let x = {MyModule.{caret} = 32}""" + + assertHasItemWithNames [ "person" ] info + +[] +let ``Identifier.InRecord.WithoutDef`` () = + let info = Checker.getCompletionInfo """type Rec = { X.{caret} : int }""" + Assert.Equal(0, info.Items.Length) + +[] +let ``Regression1911.Expression.InMatchStatement`` () = + let info = + Checker.getCompletionInfo + """ + type Thingy = { A : bool; B : int } + let test = match (List.head [{A = true; B = 0}; {A = false; B = 1}]).{caret}""" + + assertHasItemWithNames [ "A"; "B" ] info + +[] +let ``AutoComplete.Bug65731_A`` () = + let info = + Checker.getCompletionInfo + """module SomeOtherPath = + type r = { a: int; b : int } +let f1 x = { x with SomeOtherPath.{caret}a = 3 } // a""" + + assertHasItemWithNames [ "a" ] info + +[] +let ``AutoComplete.Bug65731_B`` () = + let info = + Checker.getCompletionInfo + """module SomeOtherPath = + type r = { a: int; b : int } +let f2 x = { x with SomeOtherPath.r.{caret}a = 3 } // a""" + + assertHasItemWithNames [ "a" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs new file mode 100644 index 00000000000..df38f26d2c5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs @@ -0,0 +1,16 @@ +module FSharp.Compiler.Service.Tests.CompletionRecursionTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CompletionInDifferentEnvs1`` () = + let info = + Checker.getCompletionInfo + """let f1 num = + let rec completeword d = + d + d +(**)comple{caret}""" + + assertHasItemWithNames [ "completeword" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs new file mode 100644 index 00000000000..8e6695e28a5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs @@ -0,0 +1,137 @@ +module FSharp.Compiler.Service.Tests.CompletionSeqListArrayExprsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Array.Length.InForRange`` () = + let info = + Checker.getCompletionInfo + """ +let a = [|1;2;3|] +for i in 0..a.{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.Array.AfterassertKeyword`` () = + let info = + Checker.getCompletionInfo + """ +let x = [1;2;3] +assert x.{caret}""" + + assertHasItemWithNames [ "Head" ] info + assertHasNoItemsWithNames [ "Listeners" ] info + +[] +let ``CtrlSpaceCompletion.Bug294974.Case2`` () = + let info = + Checker.getCompletionInfo + """ + let xxx {caret}= [1] + xxx .IsEmpty // Ctrl-J just before the '.' """ + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "IsEmpty" ] info + +[] +[] +[] +let ``PopupsVersusCtrlSpaceOnDotDot.FirstDot`` (_trigger: string) = + let info = Checker.getCompletionInfo "System.Console.{caret}.BackgroundColor" + + assertHasItemWithNames [ "BackgroundColor" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Identifier.OnWhiteSpace.AtTopLevel`` () = + let info = Checker.getCompletionInfo "(*marker*) {caret} " + + assertHasItemWithNames [ "System"; "Array2D" ] info + assertHasNoItemsWithNames [ "Int32" ] info + +[] +let ``Identifier.AfterDefined.Bug1545`` () = + let info = + Checker.getCompletionInfo + """ +let x = [|"hello"|] +x.{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Residues1`` () = + let info = Checker.getCompletionInfo "System . Int32 . M{caret}" + + assertHasItemWithNames [ "MaxValue"; "MinValue" ] info + assertHasNoItemsWithNames [ "MailboxProcessor"; "Map" ] info + +[] +let ``BY_DESIGN.CommonScenarioThatBegsTheQuestion.Bug73940`` () = + let info = + Checker.getCompletionInfo + """ + let r = + ["1"] + |> List.map (fun s -> s.{caret} // user previous had e.g. '(fun s -> s)' here, but he erased after 's' to end-of-line and hit '.' e.g. to eventually type '.Substring(5))' + |> List.filter (fun s -> s.Length > 5) // parser recover assumes close paren is here, and type inference goes wacky-useless with such a parse + """ + + assertHasNoItemsWithNames [ "Chars" ] info + +[] +let ``Identifier.AfterParenthesis.Bug835276`` () = + let info = + Checker.getCompletionInfo + """ +let f ( s : string ) = + let x = 10 + s.Length + for i in 1..10 do + let ok = 10 + s.Length // dot here did work + let y = 10 +(s.{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.AfterParenthesis.Bug6484_1`` () = + let info = + Checker.getCompletionInfo + """ +for x in 1..10 do + printfn "%s" (x.{caret} """ + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``Array`` () = + let info = Checker.getCompletionInfo "let arr = [| for i in 1..10 -> i |].{caret}" + + assertHasItemWithNames [ "Clone"; "IsFixedSize" ] info + +[] +let ``List`` () = + let info = Checker.getCompletionInfo "let lst = [ for i in 1..10 -> i].{caret}" + + assertHasItemWithNames [ "Head"; "Tail" ] info + +[] +let ``Expression.List`` () = + let info = Checker.getCompletionInfo "[1;2].{caret} " + + assertHasItemWithNames [ "Head"; "Item" ] info + +[] +let ``Array.InitialUsing..`` () = + let info = Checker.getCompletionInfo "let x1 = [| 0.0 .. 0.1 .. 10.0 |].{caret}" + + assertHasItemWithNames [ "Length"; "Clone"; "ToString" ] info + +[] +let ``BadCompletionAfterQuicklyTyping`` () = + let info = Checker.getCompletionInfo "[1].{caret}" + + assertHasItemWithNames [ "Length" ] info + assertHasNoItemsWithNames [ "AbstractClassAttribute" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs new file mode 100644 index 00000000000..86620ee9af6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs @@ -0,0 +1,74 @@ +module FSharp.Compiler.Service.Tests.CompletionTuplesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``NotShowInfo.ClassMemberDeclA.Bug3602`` () = + let info = + Checker.getCompletionInfo + """type Foo() = + member this.Func (x, y) = () + member (*marker*) this.{caret} +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``NotShowInfo.ClassMemberDeclB.Bug3602`` () = + let info = + Checker.getCompletionInfo + """type Foo() = + member this.Func (x, y) = () + member this.{caret} +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Expression.InLetScope`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + let p4 = + let isPalindrome x = + let chars = (string x).ToCharArray() + let len = chars.{caret} + chars + |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""" + + assertHasItemWithNames [ "IsFixedSize"; "Initialize" ] info + +[] +let ``Expression.InFunScope.FirstParameter`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + let p4 = + let isPalindrome x = + let chars = (string x).ToCharArray() + let len = chars(*Marker1*) + chars + |> Array.mapi (fun i c -> (i.{caret}, c(*Marker3*))""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``Expression.InFunScope.SecParameter`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + let p4 = + let isPalindrome x = + let chars = (string x).ToCharArray() + let len = chars(*Marker1*) + chars + |> Array.mapi (fun i c -> (i(*Marker2*), c.{caret})""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs new file mode 100644 index 00000000000..5ea0e9f02e1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs @@ -0,0 +1,190 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeAbbreviationsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Completion.DetectClasses`` () = + let sources = + [ """type X = class + inherit {caret}""" + """[] +type X = + inherit {caret}""" + """[] +type X = class + inherit {caret}""" + """[] +type X() = + inherit {caret}""" ] + + for source in sources do + let info = Checker.getCompletionInfo source + assertHasItemWithNames [ "obj" ] info + +[] +let ``Completion.DetectUnknownCompletionContext`` () = + let info = + Checker.getCompletionInfo + """type X = + inherit {caret}""" + + assertHasItemWithNames [ "obj"; "seq" ] info + +[] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule.{caret} + let b = (new NS1.MyModule.TestType())(*MarkerMethod*) + """, + true, "TestType")>] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule.{caret} + let b = (new NS1.MyModule.TestType())(*MarkerMethod*) + """, + false, "ObsoleteType;CompilerMessageType")>] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule(*MarkerType*) + let b = (new NS1.MyModule.TestType()).{caret} + """, + true, "TestMethod;VisibleMethod;VisibleMethod2")>] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule(*MarkerType*) + let b = (new NS1.MyModule.TestType()).{caret} + """, + false, "ObsoleteMethod;CompilerMessageMethod;HiddenMethod")>] +let ``DefInDiffNameSpace`` (markedSource: string) (shouldContain: bool) (names: string) = + let info = Checker.getCompletionInfo markedSource + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +let ``Regression1067.InstanceOfGenericType`` () = + let info = + Checker.getCompletionInfo + """ + type GT<'a> = + static member P = 12 + static member Q = 13 + let _ = GT(*Marker1*) + type gt_int = GT + gt_int.{caret} + type D = + class + end + let x = typeof(*Marker3*) + let y = typeof + y(*Marker4*) + """ + + assertHasItemWithNames [ "P"; "Q" ] info + +[] +let ``Regression1067.ClassUsingGenericTypeAsAttribute`` () = + let info = + Checker.getCompletionInfo + """ + type GT<'a> = + static member P = 12 + static member Q = 13 + let _ = GT(*Marker1*) + type gt_int = GT + gt_int(*Marker2*) + type D = + class + end + let x = typeof(*Marker3*) + let y = typeof + y.{caret} + """ + + assertHasItemWithNames [ "Assembly"; "FullName"; "GUID" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs new file mode 100644 index 00000000000..600aa043991 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs @@ -0,0 +1,194 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeAnnotationsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Inherit.CompletionInConstructorArguments1`` () = + let info = + Checker.getCompletionInfo + """type A(a : int) = class end +type B() = inherit A(a{caret})""" + + assertHasItemWithNames [ "abs" ] info + +[] +let ``Inherit.CompletionInConstructorArguments2`` () = + let info = + Checker.getCompletionInfo + """type A(a : int) = class end +type B() = inherit A(System.String.{caret})""" + + assertHasItemWithNames [ "Empty" ] info + assertHasNoItemsWithNames [ "Array"; "Collections" ] info + +[] +let ``ProtectedMembers.BaseClass`` () = + let info = + Checker.getCompletionInfo + """type T() = + inherit exn() + member this.Run(x : exn) = x.{caret}""" + + assertHasItemWithNames [ "Message"; "HResult" ] info + +[] +let ``BasicLocalMemberList`` () = + let info = + Checker.getCompletionInfo + """let MyFunction (s:string) = + let y="dog" + y.{caret} + ()""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``LocalMemberList.WithPartialMemberEntry1`` () = + let info = + Checker.getCompletionInfo + """let MyFunction (s:string) = + let y="dog" + y.Substri{caret} + ()""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``LocalMemberList.WithPartialMemberEntry2`` () = + let info = + Checker.getCompletionInfo + """let MyFunction (s:string) = + let y="dog" + y.{caret}Substri + ()""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``MemberInfoCompileErrorsShowInDataTip`` () = + let info = + Checker.getCompletionInfo + """type Foo = + member x.Bar() = 0 +let foovalue:Foo = unbox null +foovalue.B{caret}""" + + assertHasItemWithNames [ "Bar" ] info + +[] +let ``Identifier.Invalid.Bug876b`` () = + let info = + Checker.getCompletionInfo + """let f (x:System.Exception) = x.{caret} + for x = 0 to 0 do () done""" + + assertHasItemWithNames [ "Message"; "StackTrace" ] info + +[] +let ``Identifier.Invalid.Bug876c`` () = + let info = + Checker.getCompletionInfo + """let f (x:System.Exception) = x.{caret} + 12""" + + assertHasItemWithNames [ "Message" ] info + +[] +[] +[] +[] +let ``Identifier.IntBinderDot`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "ToString"; "Equals" ] info + +[] +[] +[] +[] +let ``Expression.AtomicStringDot`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +let ``Expression.Nested.InLetBind`` () = + let info = + Checker.getCompletionInfo + """ + let f (x : string) = () + // Nested expressions + let x = 42 |> ignore; f ("1" + "1").{caret} + """ + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``Expression.Nested.InWhileLoop`` () = + let info = + Checker.getCompletionInfo + """ + let f (x : string) = () + while true do + ignore (f ("1" + "1").{caret}) + """ + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``LongIdent.PInvoke.AsReturnType`` () = + let info = + Checker.getCompletionInfo + """ + open System.IO + open System.Runtime.InteropServices + // Get two temp files, write data into one of them + let tempFile1, tempFile2 = Path.GetTempFileName(), Path.GetTempFileName() + let writer = new StreamWriter (tempFile1) + writer.WriteLine("Some Data") + writer.Close() + // Original signature + //[] + //extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists); + [] + extern System.{caret} CopyFile_Arrays(char[] lpExistingFileName, char[] lpNewFileName, bool bFailIfExists); + let result = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) + printfn "Array %A" result""" + + assertHasItemWithNames [ "Boolean"; "Int32" ] info + +[] +let ``LongIdent.PInvoke.AsParameterType`` () = + let info = + Checker.getCompletionInfo + """ + open System.IO + open System.Runtime.InteropServices + [] + extern bool CopyFile_ArraySpaces(char [] lpExistingFileName, char []lpNewFileName, System.{caret} bFailIfExists); + let result2 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) + printfn "Array Space %A" result2""" + + assertHasItemWithNames [ "Boolean"; "Int32" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs new file mode 100644 index 00000000000..1417f8df46f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs @@ -0,0 +1,58 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeExtensionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ObjectInitializer.CompletionForSettableExtensionProperties`` () = + let info1 = + Checker.getCompletionInfo + """type A() = member this.SetXYZ(v: int) = () +module Ext = type A with member this.XYZ with set(v) = this.SetXYZ(v) +open Ext +A((**){caret})""" + + assertHasItemWithNames [ "XYZ" ] info1 + + let info2 = + Checker.getCompletionInfo + """type A() = member this.SetXYZ(v: int) = () +module Ext = type A with member this.XYZ with set(v) = this.SetXYZ(v) +A((**){caret})""" + + assertHasNoItemsWithNames [ "XYZ" ] info2 + +[] +let ``AfterMethod.Bug2296`` () = + let info = + Checker.getCompletionInfo + """type System.Int32 with + member x.Int32Member() = 0 +"".CompareTo("a").{caret}""" + + assertHasItemWithNames [ "Int32Member" ] info + +[] +let ``AfterMethod.Overloaded.Bug2296`` () = + let info = + Checker.getCompletionInfo + """type System.Boolean with + member x.BooleanMember() = 0 +"".Contains("a").{caret}""" + + assertHasItemWithNames [ "BooleanMember" ] info + +[] +let ``ObjInstance.ExtensionMethods.WithDef.Positive`` () = + let info = + Checker.getCompletionInfo + """ + open System + type System.Random with + member this.NextDice() = true + member this.DiceValue = 6 + let rnd = new System.Random() + rnd.{caret}""" + + assertHasItemWithNames [ "NextDice"; "DiceValue" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs new file mode 100644 index 00000000000..99404c7cbc9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs @@ -0,0 +1,135 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeProvidersTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``TypeProvider.VisibilityChecksForGeneratedTypes`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +type T = GeneratedType.SampleType +let t = T(5) +t.{caret}""" + + assertHasItemWithNames [ "PublicM"; "PublicProp" ] info + assertHasNoItemsWithNames [ "f"; "ProtectedProp"; "PrivateProp"; "ProtectedM"; "PrivateM" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.CtrlSpaceCompletionContains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N1.T1() +t.I{caret}""" + + assertHasItemWithNames [ "IM1" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Event.CtrlSpaceCompletionContains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.Eve{caret}""" + + assertHasItemWithNames [ "Event1" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Type.CtrlSpaceCompletionContains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +type boo = N1.T] +let ``TypeProvider.EditorHideMethodsAttribute.Type.DoesnotContain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.{caret}""" + + assertHasNoItemsWithNames [ "Equals"; "GetHashCode" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Type.Contains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.{caret}""" + + assertHasItemWithNames [ "Event1" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.Contains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N1.T1() +t.{caret}""" + + assertHasItemWithNames [ "IM1" ] info + +[] +let ``TypeProvider.TypeContainsNestedType`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +type XXX = N1.T1.{caret}""" + + assertHasItemWithNames [ "SomeNestedType" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Event.Contain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.Event1.{caret}""" + + assertHasItemWithNames [ "AddHandler"; "RemoveHandler" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Method.Contain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = N.T.M.{caret}()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Property.Contain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = N.T.StaticProp.{caret}""" + + assertHasItemWithNames [ "GetType"; "Equals" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs new file mode 100644 index 00000000000..24cd49b8049 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs @@ -0,0 +1,90 @@ +module FSharp.Compiler.Service.Tests.CompletionUnitsOfMeasureTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``UnitMeasure.Bug78932_1`` () = + let info = + Checker.getCompletionInfo + """ + module M1 = + [] type Kg + + module M2 = + let f = 1 // <- type . between M1 and ' >' => works""" + + assertHasItemWithNames [ "Kg" ] info + +[] +let ``UnitMeasure.Bug78932_2`` () = + let info = + Checker.getCompletionInfo + """ + module M1 = + [] type Kg + + module M2 = + let f = 1 // <- type . between M1 and '>' => no popup intellisense""" + + assertHasItemWithNames [ "Kg" ] info + +[] +let ``UnitMeasure.UnitNames`` () = + let info = + Checker.getCompletionInfo + """Microsoft.FSharp.Data.UnitSystems.SI.UnitNames.{caret}""" + + assertHasItemWithNames + [ "ampere"; "becquerel"; "candela"; "coulomb"; "farad"; "gray"; "henry"; "hertz"; "joule"; "katal"; "kelvin"; "kilogram"; "lumen"; "lux"; "metre"; "mole"; "newton"; "ohm"; "pascal"; "second"; "siemens"; "sievert"; "tesla"; "volt"; "watt"; "weber" ] + info + +[] +let ``UnitMeasure.UnitSymbols`` () = + let info = + Checker.getCompletionInfo + """Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols.{caret}""" + + assertHasItemWithNames + [ "A"; "Bq"; "C"; "F"; "Gy"; "H"; "Hz"; "J"; "K"; "N"; "Pa"; "S"; "Sv"; "T"; "V"; "W"; "Wb"; "cd"; "kat"; "kg"; "lm"; "lx"; "m"; "mol"; "ohm"; "s" ] + info + +[] +[] 'a> = [1; 2; 3] + let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 + let y = int System.IO(*Maftervariable5*)""")>] +[] 'a> = 10""")>] +let ``UnitMeasure.AsTypeParameter.DefFromDiffNamespace`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ "DuType"; "Pet"; "Dog" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index f1dd58b7edd..fb359909d0f 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -6,23 +6,6 @@ open FSharp.Test.Assert open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts open Xunit -let private assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = - let itemNames = - completionInfo.Items - |> Array.map _.NameInCode - |> Array.map normalizeNewLines - |> set - - for name in names do - let name = normalizeNewLines name - Set.contains name itemNames |> shouldEqual contains - -let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = - assertItemsWithNames true names completionInfo - -let assertHasNoItemsWithNames names (completionInfo: DeclarationListInfo) = - assertItemsWithNames false names completionInfo - [] let ``Expr - After record decl 01`` () = let info = Checker.getCompletionInfo """ @@ -439,9 +422,6 @@ module Options = let assertItemAllowed name source = assertItemWithOptions [allowObsoleteOptions] name source - let assertItemNotAllowed name source = - assertItemWithOptions [disallowObsoleteOptions] name source - [] let ``Prop - Instance 01`` () = assertItem "Prop" """ diff --git a/tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs b/tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs new file mode 100644 index 00000000000..337794606a8 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs @@ -0,0 +1,538 @@ +namespace FSharp.Compiler.Service.Tests + +open System +open System.IO +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.EditorServices +open FSharp.Compiler.IO +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts +open TestFramework + +[] +module EditorServiceAsserts = + let isIdentChar c = + Char.IsLetterOrDigit c || c = '_' || c = '\'' + + let private markAtOffset (offsetInMarker: string -> int) (source: string) (marker: string) = + match source.IndexOf(marker, StringComparison.Ordinal) with + | -1 -> failwithf "Marker %A not found in source" marker + | i -> source.Insert(i + offsetInMarker marker, "{caret}") + + let markAtStartOfMarker = markAtOffset (fun _ -> 0) + + let markAtEndOfMarker = markAtOffset (fun marker -> marker.Length) + + let markCaretAfterLeadingIdent = markAtOffset (fun marker -> marker |> Seq.takeWhile isIdentChar |> Seq.length) + + let findCompletionItem (name: string) (completionInfo: DeclarationListInfo) = + let norm = normalizeNewLines name + + match completionInfo.Items |> Array.tryFind (fun i -> normalizeNewLines i.NameInCode = norm || i.NameInList = name) with + | Some item -> item + | None -> + let names = completionInfo.Items |> Array.map _.NameInCode |> String.concat ", " + failwithf "Expected a completion item named %A but found none. Items: [%s]" name names + + let assertItemGlyph (name: string) (glyph: FSharpGlyph) (completionInfo: DeclarationListInfo) = + let item = findCompletionItem name completionInfo + + if item.Glyph <> glyph then + failwithf "Item %A has glyph %A but expected %A" name item.Glyph glyph + + let groupMainDescriptions (ToolTipText elements) = + elements + |> List.collect (fun e -> + match e with + | ToolTipElement.Group items -> items |> List.map (fun d -> taggedTextToString d.MainDescription) + | _ -> []) + + let flattenItemDescription (tooltip: ToolTipText) = + groupMainDescriptions tooltip |> String.concat "\n" + + let assertItemDescriptionOccurrences (expected: int) (itemName: string) (token: string) (completionInfo: DeclarationListInfo) = + let item = findCompletionItem itemName completionInfo + let descr = flattenItemDescription item.Description + let occurrences = descr.Split([| token |], StringSplitOptions.None).Length - 1 + + if occurrences <> expected then + failwithf "Item %A: expected %d occurrence(s) of %A but found %d (description: %s)" itemName expected token occurrences descr + + let assertItemDescriptionContainsExactlyOnce itemName token completionInfo = + assertItemDescriptionOccurrences 1 itemName token completionInfo + + let private itemsWithPrefix (prefix: string) (ignoreCase: bool) (completionInfo: DeclarationListInfo) = + let cmp = + if ignoreCase then StringComparison.OrdinalIgnoreCase else StringComparison.Ordinal + + completionInfo.Items + |> Array.map _.NameInCode + |> Array.filter (fun n -> n.StartsWith(prefix, cmp)) + + let private assertPrefixUniqueness (unique: bool) (prefix: string) (ignoreCase: bool) (completionInfo: DeclarationListInfo) = + let matches = itemsWithPrefix prefix ignoreCase completionInfo + let ok = if unique then matches.Length = 1 else matches.Length >= 2 + + if not ok then + let expectation = if unique then "exactly ONE item" else "AT LEAST TWO items" + + failwithf "Expected %s whose NameInCode start(s) with %A (ignoreCase=%b) but found %d: [%s]" + expectation prefix ignoreCase matches.Length (String.concat ", " matches) + + let assertPrefixIsUnique = assertPrefixUniqueness true + + let assertPrefixIsNotUnique = assertPrefixUniqueness false + + let private expectedLineOf (definitionLine: string) (sourceLines: string array) = + match sourceLines |> Array.indexed |> Array.filter (fun (_, l) -> l.Contains definitionLine) with + | [| (i, _) |] -> i + 1 + | [||] -> failwithf "Definition line containing %A was not found in the source" definitionLine + | many -> + failwithf + "Definition line %A is AMBIGUOUS — it matches %d source lines (1-based: %A); use a more specific substring" + definitionLine many.Length (many |> Array.map (fun (i, _) -> i + 1)) + + let private assertLandedOnLine (landedPrefix: string) (definitionLine: string) (sourceLines: string array) (expectedLine: int) result = + match result with + | FindDeclResult.DeclFound range when range.StartLine = expectedLine -> () + | FindDeclResult.DeclFound range -> + let landedText = + if range.StartLine >= 1 && range.StartLine <= sourceLines.Length then + sourceLines.[range.StartLine - 1] + else + "" + + failwithf "%s landed on line %d (%s) but expected line %d (containing %A)" + landedPrefix range.StartLine landedText expectedLine definitionLine + | other -> + failwithf "Expected FindDeclResult.DeclFound on line %d (containing %A) but got %A" + expectedLine definitionLine other + + let assertGoToDefinitionOnLine (definitionLine: string) (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context) + + let sourceLines = context.Source.Replace("\r\n", "\n").Split('\n') + let expectedLine = expectedLineOf definitionLine sourceLines + assertLandedOnLine "Goto-def" definitionLine sourceLines expectedLine result + + let assertGoToDefinitionFails (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context) + + match result with + | FindDeclResult.DeclFound range -> + failwithf "Expected goto-def to fail (not DeclFound), but it found a definition at %A" range + | _ -> () + + let assertGoToDefinitionIsExternal (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context) + + match result with + | FindDeclResult.ExternalDecl _ -> () + | other -> + failwithf "Expected FindDeclResult.ExternalDecl (resolved-but-external), but got %A" other + + let assertGoToDefinitionOperatorOnLine (definitionLine: string) (operatorName: string) (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context.Pos.Line, context.Pos.Column + 1, context.LineText, [ operatorName ]) + + let sourceLines = context.Source.Replace("\r\n", "\n").Split('\n') + let expectedLine = expectedLineOf definitionLine sourceLines + assertLandedOnLine "Operator goto-def" definitionLine sourceLines expectedLine result + + let assertGoToDefinitionToExternalLine (definitionLine: string) (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context) + + match result with + | FindDeclResult.DeclFound range when File.Exists range.FileName -> + let landedLines = + File.ReadAllText(range.FileName).Replace("\r\n", "\n").Split('\n') + + let landedText = + if range.StartLine >= 1 && range.StartLine <= landedLines.Length then + landedLines.[range.StartLine - 1] + else + "" + + if not (landedText.Contains definitionLine) then + failwithf "Goto-def landed on %s:%d (%s) but expected a line containing %A" + range.FileName range.StartLine landedText definitionLine + | FindDeclResult.DeclFound _ -> () + | other -> + failwithf "Expected FindDeclResult.DeclFound on a line containing %A but got %A" definitionLine other + + let assertNoDiagnostics (results: FSharpCheckFileResults) = + match dumpDiagnostics results with + | [] -> () + | msgs -> + failwithf "Expected no diagnostics, but got %d:\n%s" msgs.Length (String.concat "\n" msgs) + + let assertDiagnosticCount (expected: int) (results: FSharpCheckFileResults) = + let msgs = dumpDiagnostics results |> List.distinct + if msgs.Length <> expected then + failwithf "Expected %d distinct diagnostic(s), but got %d:\n%s" expected msgs.Length (String.concat "\n" msgs) + + let assertDiagnosticsContain (expected: string) (results: FSharpCheckFileResults) = + let messages = results.Diagnostics |> Array.map normalizeDiagnosticMessage + if not (messages |> Array.exists (fun m -> m.Contains expected)) then + let dump = dumpDiagnostics results + failwithf "Expected a diagnostic message containing %A, but got %d:\n%s" + expected dump.Length (String.concat "\n" dump) + + let assertSingleDiagnosticContainingAll (parts: string list) (results: FSharpCheckFileResults) = + let dump = dumpDiagnostics results |> List.distinct + match dump with + | [ single ] -> + match parts |> List.filter (fun p -> not (single.Contains p)) with + | [] -> () + | missing -> + failwithf "Single diagnostic is missing expected part(s) %A:\n%s" missing single + | _ -> + failwithf "Expected exactly 1 distinct diagnostic, but got %d:\n%s" + dump.Length (String.concat "\n" dump) + + let assertWarningCount (expected: int) (results: FSharpCheckFileResults) = + let warnings = dumpDiagnosticsOfSeverity FSharpDiagnosticSeverity.Warning results |> List.distinct + + if warnings.Length <> expected then + failwithf "Expected %d warning(s), but got %d:\n%s" + expected warnings.Length (String.concat "\n" warnings) + + let checkAsFsFile (source: string) = + let fileName, options = mkTestFileAndOptions [||] + let _, checkResults = parseAndCheckFile fileName source options + checkResults + + let getTooltipWithReferences (name: string) (references: string list) (markedSource: string) = + let context = Checker.getResolveContext markedSource + let fileName = name + ".fsx" + + let args = + [| "--simpleresolution" + "--noframework" + "--debug:full" + "--define:DEBUG" + "--optimize-" + "--out:" + name + ".dll" + "--warn:3" + "--fullpaths" + "--flaterrors" + "--target:library" + yield! references |> List.map (fun r -> "-r:" + r) |] + + let options = + { checker.GetProjectOptionsFromCommandLineArgs(name + ".fsproj", args) with + SourceFiles = [| fileName |] } + + let _, checkResults = parseAndCheckFile fileName context.Source options + checkResults.GetTooltip(context) + + let foldToolTip (ToolTipText items) = + items + |> List.collect (fun item -> + match item with + | ToolTipElement.Group elements -> + elements + |> List.collect (fun e -> + [ taggedTextToString e.MainDescription + match e.XmlDoc with + | FSharpXmlDoc.FromXmlText xmlDoc -> String.concat "\n" xmlDoc.UnprocessedLines + | _ -> "" + match e.Remarks with + | Some r -> taggedTextToString r + | None -> "" ]) + | ToolTipElement.CompositionError err -> [ err ] + | ToolTipElement.None -> []) + |> String.concat "\n" + + type TooltipSource = + | Script + | FsFile + + let foldedTooltip (mode: TooltipSource) (markedSource: string) : string = + match mode with + | Script -> foldToolTip (Checker.getTooltip markedSource) + | FsFile -> + let context = Checker.getResolveContext markedSource + let checkResults = checkAsFsFile context.Source + + checkResults.GetTooltip(context) + |> foldToolTip + + let private tooltipSourceLabel mode = + match mode with + | Script -> "tooltip" + | FsFile -> ".fs-file tooltip" + + let assertFoldedTooltipContains (contains: bool) (label: string) (expected: string) (actual: string) = + if actual.Contains expected <> contains then + let relation = if contains then "to contain" else "NOT to contain" + failwithf "Expected %s %s %A, but the actual tooltip was:\n%s" label relation expected actual + + let private assertTooltip (contains: bool) (mode: TooltipSource) (expected: string) (markedSource: string) = + assertFoldedTooltipContains contains (tooltipSourceLabel mode) expected (foldedTooltip mode markedSource) + + let assertTooltipContains = assertTooltip true Script + + let walk (source: string) (initial: string) (ident: string) (expected: string) = + let baseIndex = source.IndexOf(initial, StringComparison.Ordinal) + + for i in 0 .. ident.Length - 1 do + let marked = source.Insert(baseIndex + initial.Length + i + 1, "{caret}") + assertTooltipContains expected marked + + let assertTooltipDoesNotContain = assertTooltip false Script + + let assertIdentifierInTooltipExactlyOnce (ident: string) (markedSource: string) = + let actual = foldToolTip (Checker.getTooltip markedSource) + + if not (actual.Contains ident) then + failwithf "Expected tooltip to contain %A at least once (non-vacuity), but the actual tooltip was:\n%s" ident actual + + let count = + actual.Split([| '='; '.'; ' '; '\t'; '('; ':'; ')'; '\n'; '\r' |]) + |> Array.filter ((=) ident) + |> Array.length + + if count <> 1 then + failwithf "Expected identifier %A to occur exactly once in the tooltip, but it occurred %d time(s):\n%s" ident count actual + + let assertStringContainsInOrder (parts: string list) (actual: string) = + let mutable fromIndex = 0 + for part in parts do + match actual.IndexOf(part, fromIndex, StringComparison.Ordinal) with + | -1 -> + failwithf "Expected tooltip to contain %A after index %d (in order), but the actual tooltip was:\n%s" + part fromIndex actual + | index -> fromIndex <- index + part.Length + + let assertTooltipContainsInOrder (parts: string list) (markedSource: string) = + let actual = foldToolTip (Checker.getTooltip markedSource) + assertStringContainsInOrder parts actual + + let assertCompletionItemTooltipContainsInOrder (itemName: string) (parts: string list) (markedSource: string) = + let item = findCompletionItem itemName (Checker.getCompletionInfo markedSource) + assertStringContainsInOrder parts (foldToolTip item.Description) + + let assertTooltipContainsInFsFile = assertTooltip true FsFile + + let assertTooltipDoesNotContainInFsFile = assertTooltip false FsFile + + let fsTestLibCode = """namespace FSTestLib + + /// DocComment: This is MyStruct type, represents a struct. + type MyPoint = + struct + val mutable private m_X : float + val mutable private m_Y : float + + new (x, y) = { m_X = x; m_Y = y } + + /// Gets and sets X + member this.X with get () = this.m_X and set x = this.m_X <- x + + /// Gets and sets Y + member this.Y with get () = this.m_Y and set y = this.m_Y <- y + + // Length of given Point + member this.Len = sqrt ( this.X * this.X + this.Y * this.Y ) + + static member (+) (p1 : MyPoint, p2 : MyPoint) = MyPoint(p1.X + p2.X, p1.Y + p2.Y) + + end + + [] + /// DocComment: This is my record type. + type MyEmployee = + { mutable Name : string; + mutable Age : int; + /// DocComment: Indicates whether the employee is full time or not + mutable IsFTE : bool } + + interface System.IComparable with + member this.CompareTo (emp : obj) = + let r = emp :?> MyEmployee + match r.IsFTE && this.IsFTE with + | true -> this.Age - r.Age + | _ -> System.Convert.ToInt32(this.IsFTE) - System.Convert.ToInt32(r.IsFTE) + + override this.ToString() = sprintf "%s is %d." this.Name this.Age + + /// DocComment: Method + static member MakeDummy () = + { Name = System.String.Empty; Age = -1; IsFTE = false } + + // TODO: Normally there's no DotCompletion after "this" here + override this.Equals(ob : obj) = + let r = ob :?> MyEmployee + this.Name = r.Name && this.Age = r.Age && this.IsFTE = r.IsFTE + + /// DocComment: This is my interface type + type IMyInterface = + interface + /// DocComment: abstract method in Interface + abstract Represent : unit -> string + end + + // TODO: add formatable ToString() + /// DocComment: This is my discriminated union type + type MyDistance = + | Kilometers of float + | Miles of float + | NauticalMiles of float + + + /// DocComment: Static Method + static member toMiles x = + Miles( + match x with + | Miles x -> x + | Kilometers x -> x / 1.6 + | NauticalMiles x -> x * 1.15 + ) + + /// DocComment: Property + member this.toNautical = + NauticalMiles( + match this with + | Kilometers x -> x / 1.852 + | Miles x -> x / 1.15 + | NauticalMiles x -> x + ) + + /// DocComment: Method + member this.IncreaseBy dist = + match this with + | Kilometers x -> Kilometers (x + dist) + | Miles x -> Miles (x + dist) + | NauticalMiles x -> NauticalMiles (x + dist) + + /// DocComment: Event + static member Event = + let evnt = new Event() + evnt + + /// DocComment: This is my enum type + type MyColors = + | /// DocComment: Field + Red = 0 + | Green = 1 + | Blue = 2 + + /// DocComment: This is my class type + type MyCar( number: int, color:MyColors) = + /// DocComment: This is static field + static member Owner = "MySelf" + /// DocComment: This is instance field + member this.Number = number + member this.Color = color + /// DocComment: This is static method + static member Run (number:int) = printf "%s" (number.ToString()+"Running") + /// DocComment: This is instance method + member this.Repair (expense:int) = printf "%s" ("Spent " + expense.ToString() + " for repairing. ") + + /// DocComment: This is my delegate type + type ControlEventHandler = delegate of int -> unit""" + + let foldedProjectTooltip (priorFiles: string list) (extraRefs: string list) (markedSource: string) = + let context = Checker.getResolveContext markedSource + let options = createProjectOptions (priorFiles @ [ context.Source ]) [ for r in extraRefs -> "-r:" + r ] + let queriedPath = Array.last options.SourceFiles + let _, checkResults = parseAndCheckFile queriedPath context.Source options + checkResults.GetTooltip(context) |> foldToolTip + + let assertTooltipContainsWithFsTestLib (expected: string) (markedFile2: string) = + foldedProjectTooltip [ fsTestLibCode ] [] markedFile2 + |> assertFoldedTooltipContains true "FSTestLib two-file tooltip" expected + + let assertCompleteIdentifierIslandWithTolerate (tolerate: bool) (expected: string option) (sourceWithCaretMarker: string) = + let n = sourceWithCaretMarker.IndexOf '$' + if n < 0 then failwith "source must contain the '$' caret marker" + let line = sourceWithCaretMarker.Remove(n, 1) + + match QuickParse.GetCompleteIdentifierIsland tolerate line n, expected with + | Some(island, _, _), Some exp -> + if island <> exp then + failwithf "tolerate=%b: GetCompleteIdentifierIsland returned island %A but expected %A (line=%A col=%d)" tolerate island exp line n + | None, None -> () + | Some(island, _, _), None -> + failwithf "tolerate=%b: expected NO island but got %A (line=%A col=%d)" tolerate island line n + | None, Some exp -> + failwithf "tolerate=%b: expected island %A but got None (line=%A col=%d)" tolerate exp line n + + let assertCompleteIdentifierIsland (expected: string option) (sourceWithCaretMarker: string) = + assertCompleteIdentifierIslandWithTolerate true expected sourceWithCaretMarker + assertCompleteIdentifierIslandWithTolerate false expected sourceWithCaretMarker + + let private getMethodGroup (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + checkResults.GetMethods(context.Pos.Line, context.Pos.Column, context.LineText, Some context.Names) + + let private paramDisplays (m: MethodGroupItem) = + m.Parameters |> Array.map (fun p -> taggedTextToString p.Display) |> Array.toList + + let private describeMethodGroup (mg: MethodGroup) = + if mg.Methods.Length = 0 then + " " + else + mg.Methods + |> Array.mapi (fun i m -> sprintf " [%d] %s" i (String.concat ", " (paramDisplays m))) + |> String.concat "\n" + + let private displaysMatch (expected: string list) (displays: string list) = + expected.Length = displays.Length + && List.forall2 (fun (e: string) (d: string) -> d.Contains e) expected displays + + let assertParameterInfoOverloads (expected: string list list) (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length <> expected.Length then + failwithf "Expected %d overload(s) but got %d:\n%s" expected.Length mg.Methods.Length (describeMethodGroup mg) + for m in mg.Methods do + let displays = paramDisplays m + let matched = expected |> List.exists (fun exp -> displaysMatch exp displays) + if not matched then + failwithf "Overload [%s] matched no expected set %A:\n%s" (String.concat ", " displays) expected (describeMethodGroup mg) + + let assertNoParameterInfo (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length <> 0 then + failwithf "Expected no parameter info but got %d overload(s):\n%s" mg.Methods.Length (describeMethodGroup mg) + + let assertParameterInfoContains (expected: string list) (markedSource: string) = + let mg = getMethodGroup markedSource + let matched = + mg.Methods + |> Array.exists (fun m -> displaysMatch expected (paramDisplays m)) + if not matched then + failwithf "No overload matched expected %A:\n%s" expected (describeMethodGroup mg) + + let assertParameterInfoOverloadIndex (idx: int) (expected: string list) (markedSource: string) = + let mg = getMethodGroup markedSource + if idx < 0 || idx >= mg.Methods.Length then + failwithf "No overload at index %d (have %d):\n%s" idx mg.Methods.Length (describeMethodGroup mg) + let displays = paramDisplays mg.Methods[idx] + if not (displaysMatch expected displays) then + failwithf "Overload [%d] = [%s] did not match expected %A:\n%s" idx (String.concat ", " displays) expected (describeMethodGroup mg) + + let assertHasParameterInfo (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length = 0 then + failwith "Expected a method group with parameter info, but got none" + + let assertFirstReturnTypeText (expected: string) (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length = 0 then + failwithf "Expected a method group, but got none. Looking for return type %A" expected + let actual = taggedTextToString mg.Methods[0].ReturnTypeText + if actual <> expected then + failwithf "Expected first overload return type %A but got %A:\n%s" expected actual (describeMethodGroup mg) diff --git a/tests/FSharp.Compiler.Service.Tests/EditorTests.fs b/tests/FSharp.Compiler.Service.Tests/EditorTests.fs index 47ad18e8633..be06517681c 100644 --- a/tests/FSharp.Compiler.Service.Tests/EditorTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/EditorTests.fs @@ -1991,15 +1991,6 @@ let hasRecordType (recordTypeName: string) (symbolUses: FSharpSymbolUse list) = ) |> fun exists -> Assert.True(exists, $"Record type {recordTypeName} not found.") -let private assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = - let itemNames = completionInfo.Items |> Array.map _.NameInCode |> set - - for name in names do - Assert.True(Set.contains name itemNames = contains) - -let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = - assertItemsWithNames true names completionInfo - [] let ``Record fields are completed via type name usage`` () = let parseResults, checkResults = diff --git a/tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs b/tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs new file mode 100644 index 00000000000..d77e04af881 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs @@ -0,0 +1,483 @@ +module FSharp.Compiler.Service.Tests.ErrorListTests + +open Xunit +open FSharp.Test + +[] +let ``OverloadsAndExtensionMethodsForGenericTypes`` () = + let _, checkResults = getParseAndCheckResults """ +open System.Linq + +type T = + abstract Count : int -> bool + default this.Count(_ : int) = true + + interface System.Collections.Generic.IEnumerable with + member this.GetEnumerator() : System.Collections.Generic.IEnumerator = failwith "not implemented" + interface System.Collections.IEnumerable with + member this.GetEnumerator() : System.Collections.IEnumerator = failwith "not implemented" + +let g (t : T) = t.Count() +""" + assertNoDiagnostics checkResults + +[] +let ``ErrorsInScriptFile`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"System\"\n#r \"System2\"\n" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "Assembly reference 'System2' was not found or is invalid" checkResults + +[] +let ``LineDirective`` () = + let _, checkResults = getParseAndCheckResults """ +# 100 "foo.fs" +let x = y +""" + assertDiagnosticsContain "The value or constructor 'y' is not defined" checkResults + +[] +let ``InvalidConstructorOverload`` () = + let _, checkResults = getParseAndCheckResults """ +type X private() = + new(_ : int) = X() + new(_ : bool) = X() + new(_ : float, _ : int) = X() +X(1.0) +""" + assertSingleDiagnosticContainingAll + [ "No overloads match for method 'X'." + "Available overloads:" + "new: bool -> X" + "new: int -> X" ] + checkResults + +[] +let ``Query.InvalidJoinRelation.GroupJoin`` () = + let _, checkResults = getParseAndCheckResults """ +let x = query { + for x in [1] do + groupJoin y in [2] on ( x < y) into g + select x } +""" + assertDiagnosticsContain "Invalid join relation in 'groupJoin'." checkResults + +[] +[] +[] +let ``Query.NonOpenedNullableModule - nullable operator cannot be resolved`` (source: string) = + let _, checkResults = getParseAndCheckResults source + assertDiagnosticsContain "The operator '?=?' cannot be resolved." checkResults + +[] +let ``Query.InvalidJoinRelation.Join`` () = + let _, checkResults = getParseAndCheckResults """ +let x = + query { + for x in [1] do + join y in [""] on (x > y) + select 1 + } +""" + assertDiagnosticsContain "Invalid join relation in 'join'." checkResults + +let invalidMethodOverloadCases: obj[] seq = + [ + [| box """ +System.Console.WriteLine(null) +""" + box [ "A unique overload for method 'WriteLine' could not be determined" + "Candidates:" + "System.Console.WriteLine(value: obj) : unit" + "System.Console.WriteLine(value: string) : unit" ] |] + [| box """ +type A<'T>() = + member this.Do(a : int, b : 'T) = () + member this.Do(a : int, b : int) = () +type B() = + inherit A() + +let b = B() +b.Do(1, 1) +""" + box [ "A unique overload for method 'Do' could not be determined" + "Candidates:" + "member A.Do: a: int * b: 'T -> unit" + "member A.Do: a: int * b: int -> unit" ] |] + ] + +[] +let ``InvalidMethodOverload`` (source: string) (expectedParts: string list) = + let _, checkResults = getParseAndCheckResults source + assertSingleDiagnosticContainingAll expectedParts checkResults + +[] +let ``NoErrorInErrList`` () = + let _, checkResults = getParseAndCheckResults """ +module NoErrors2 + +module DictionaryExtension = + + type System.Collections.Generic.IDictionary<'k,'v> with + member this.TryLookup(key : 'k) = + let mutable value = Unchecked.defaultof<'v> + if this.TryGetValue(key, &value) then + Some value + else + None + +open DictionaryExtension +""" + assertNoDiagnostics checkResults + +[] +let ``NoLevel4Warning`` () = + let _, checkResults = getParseAndCheckResults """ +namespace testerrorlist +module nolevel4warnings = + let x = System.DateTime.Now - System.DateTime.Now + x.Add(x) |> ignore +""" + assertNoDiagnostics checkResults + +[] +let ``TestWrongKeywordInInterfaceImplementation`` () = + let _, checkResults = getParseAndCheckResults """ +type staticInInterface = + class + interface System.IDisposable with + static member Foo() = () + member x.Dispose() = () + end + end +""" + assertDiagnosticsContain "No static abstract member was found that corresponds to this override" checkResults + +[] +let ``TypeProvider.MultipleErrors`` () = + let _, checkResults = getParseAndCheckResults "type Err = TPErrors.TP<1>" + assertDiagnosticsContain "type provider" checkResults + +[] +let ``Records.ErrorList.IncorrectBindings1`` () = + for code in [ "{_}"; "{_ = }" ] do + let _, checkResults = getParseAndCheckResults code + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "Field bindings must have the form 'id = expr;'" checkResults + assertDiagnosticsContain "'_' cannot be used as field name" checkResults + +[] +let ``Records.ErrorList.IncorrectBindings2`` () = + let _, checkResults = getParseAndCheckResults "{_ = 1}" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "'_' cannot be used as field name" checkResults + +[] +let ``Records.ErrorList.IncorrectBindings3`` () = + let _, checkResults = getParseAndCheckResults "{a = 1; _; _ = 1}" + assertDiagnosticCount 3 checkResults + let messages = dumpDiagnostics checkResults |> List.distinct + Assert.Equal(2, messages |> List.filter (fun m -> m.Contains "'_' cannot be used as field name") |> List.length) + Assert.Equal(1, messages |> List.filter (fun m -> m.Contains "Field bindings must have the form 'id = expr;'") |> List.length) + +[] +let ``TypeProvider.StaticParameters.IncorrectType`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const 42,2>""" + assertDiagnosticsContain "but here has type" checkResults + +[] +let ``TypeProvider.StaticParameters.Incorrect`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const " ",2>""" + assertDiagnosticsContain "An error occurred applying the static arguments to a provided type" checkResults + +[] +let ``TypeProvider.StaticParameters.IncorrectNumberOfParameter`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const "Hello World">""" + assertDiagnosticsContain "requires a value" checkResults + +[] +let ``TypeProvider.ProhibitedMethods`` () = + let _, checkResults = getParseAndCheckResults "let x = BadMethods.Arr.GetFirstElement([||])" + assertDiagnosticsContain "reported an error in the context of provided type" checkResults + +[] +let ``TypeProvider.StaticParameters.ErrorListItem`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const "Hello World",2>""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "The namespace or module 'N1' is not defined." checkResults + +[] +let ``TypeProvider.StaticParameters.NoErrorListCount`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const "Hello World",2>""" + assertNoDiagnostics checkResults + +[] +let ``NoError.FlagsAndSettings.TargetOptionsRespected`` () = + let _, checkResults = + getParseAndCheckResultsWithOptions [| "--nowarn:44" |] """ +[] +let fn x = 0 +let y = fn 1 +""" + assertNoDiagnostics checkResults + +[] +let ``UnicodeCharacters`` () = + let _, checkResults = getParseAndCheckResults "namespace 新規baApplication5" + assertDiagnosticsContain "新規" checkResults + +[] +let ``NoWarn.Bug5424`` () = + let _, checkResults = getParseAndCheckResults """ +#nowarn "67" // this type test or downcast will always hold +#nowarn "66" // this upcast is unnecessary - the types are identical +namespace Namespace1 + module Test = + open System + let a = ((5 :> obj) :?> Object) + let b = a :> obj +""" + assertNoDiagnostics checkResults + +[] +let ``FlagsAndSettings.ErrorsInFlagsDisplayed`` () = + let _, checkResults = + getParseAndCheckResultsWithOptions [| "--versionfile:nonexistent" |] """ +let x = 1 +""" + assertDiagnosticsContain "Invalid version file" checkResults + assertDiagnosticsContain "nonexistent" checkResults + +[] +let ``CompilerErrorsInErrList1`` () = + let _, checkResults = getParseAndCheckResults """ +namespace Errorlist +module CompilerError = + + let a = NoVal +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "The value or constructor 'NoVal' is not defined" checkResults + +[] +let ``CompilerErrorsInErrList6`` () = + let _, checkResults = getParseAndCheckResults """ +type EnumOfBigInt = + | A = 0I + | B = 0I + +type EnumOfNatNum = + | A = 0N + | B = 0N +""" + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "is not a valid value for an enumeration literal" checkResults + +[] +let ``CompilerErrorsInErrList7`` () = + let _, checkResults = getParseAndCheckResults """ +type EnumType = + | A = 1 + | B = 2 + +type CustomAttrib(a:int, b:string, c:float, d:EnumType) = + inherit System.Attribute() + +let a = 42 +let b = "str" +let c = 3.141 +let d = EnumType.A + +[] +type SomeClass() = + override this.ToString() = "SomeClass" + +[] +let main0 args = () + +let foo = 1 +""" + assertDiagnosticCount 5 checkResults + assertDiagnosticsContain "is not a valid constant expression or custom attribute value" checkResults + +[] +let ``CompilerErrorsInErrList9`` () = + let _, checkResults = getParseAndCheckResults """ +namespace NS + [] + type Lib() = + class + abstract M : int -> int + end + +namespace NS + module M = + type Lib with + override x.M i = i +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "Method overrides and interface implementations are not permitted here" checkResults + +[] +let ``CompilerErrorsInErrList10`` () = + let _, checkResults = getParseAndCheckResults """ +namespace Errorlist +module CompilerError = + + printfn "%A" System.Windows.Forms.Application.UserAppDataPath +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "'Forms' is not defined" checkResults + +[] +let ``DoubleClickErrorListItem`` () = + let _, checkResults = getParseAndCheckResults """ +let x = x +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "The value or constructor 'x' is not defined" checkResults + +[] +let ``FixingCodeAfterBuildRemovesErrors01`` () = + let _, checkResults = getParseAndCheckResults """ +let x = 4 + "x" +""" + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "does not match the type" checkResults + +[] +let ``FixingCodeAfterBuildRemovesErrors02`` () = + let _, checkResults = getParseAndCheckResults "let x = 4" + assertNoDiagnostics checkResults + +[] +let ``IncompleteExpression`` () = + let checkResults = + checkAsFsFile """module Test + +printfn "%A" + +List.map (fun x -> x + 1) +""" + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "This expression is a function value, i.e. is missing arguments" checkResults + +[] +let ``IntellisenseRequest`` () = + let _, checkResults = getParseAndCheckResults """ +type Foo() = + member a.B(*Marker*) : int = "1" +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "This expression was expected to have type 'int' but here has type 'string'" checkResults + +[] +[] +[] +let ``TypeChecking - error count`` (source: string) = + let _, checkResults = getParseAndCheckResults source + assertDiagnosticCount 1 checkResults + +[] +[] +[] +let ``TypeChecking - error message`` (source: string) (expected: string) = + let _, checkResults = getParseAndCheckResults source + assertDiagnosticsContain expected checkResults + +[] +let ``Warning.ConsistentWithLanguageService`` () = + let _, checkResults = getParseAndCheckResults """ +open System +mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin +mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" + assertWarningCount 20 checkResults + assertDiagnosticsContain "is reserved for future use by F#" checkResults + +[] +let ``Warning.ConsistentWithLanguageService.Comment`` () = + let _, checkResults = getParseAndCheckResults """ +open System +//mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin +//mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" + assertWarningCount 0 checkResults + +[] +let ``Errorlist.WorkwithoutNowarning`` () = + let _, checkResults = getParseAndCheckResults """ +type Fruit (shelfLife : int) as x = + let mutable m_age = (fun () -> x) +#nowarn "47" +""" + assertDiagnosticCount 1 checkResults + +[] +let ``CompilerErrorsInErrList4`` () = + let _, checkResults = getParseAndCheckResults """ +#nowarn "47" + +type Fruit (shelfLife : int) as x = + + let mutable m_age = (fun () -> x) + +#nowarn "25" // FS0025: Incomplete pattern matches on this expression. For example, the value 'C' + +type DU = A | B | C +let f x = function A -> true | B -> false + +let _fsyacc_gotos = [| 0us; 1us; 2us|] +""" + assertNoDiagnostics checkResults diff --git a/tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs b/tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs new file mode 100644 index 00000000000..688d85d09b6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs @@ -0,0 +1,356 @@ +[] +module FSharp.Compiler.Service.Tests.ScriptDiagnosticsTests + +open System +open System.IO +open Xunit +open FSharp.Test +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.Text + +let private closure (files: (string * string) list) (active: string) : FSharpDiagnostic[] = + let dir = Path.Combine(Path.GetTempPath(), "sdt_" + Guid.NewGuid().ToString("N")) + Directory.CreateDirectory(dir) |> ignore + try + for (name, content) in files do + File.WriteAllText(Path.Combine(dir, name), content) + let activePath = Path.Combine(dir, active) + let source = File.ReadAllText activePath + let options, _ = +#if NETCOREAPP + checker.GetProjectOptionsFromScript(activePath, SourceText.ofString source, assumeDotNetFramework = false, useSdkRefs = true) |> Async.RunImmediate +#else + checker.GetProjectOptionsFromScript(activePath, SourceText.ofString source) |> Async.RunImmediate +#endif + let results = checker.ParseAndCheckProject(options) |> Async.RunImmediate + results.Diagnostics + finally + try Directory.Delete(dir, true) with _ -> () + +let private distinctDiags (diags: FSharpDiagnostic[]) = + diags + |> Array.map (fun d -> formatDiagnostic d, normalizeDiagnosticMessage d) + |> Array.distinctBy fst + +let private closureDump (diags: FSharpDiagnostic[]) = + distinctDiags diags |> Array.map fst |> String.concat "\n" + +let private assertClosureNoDiagnostics (diags: FSharpDiagnostic[]) = + if diags.Length > 0 then + failwithf "Expected no diagnostics, but got %d:\n%s" diags.Length (closureDump diags) + +let private assertClosureContains (text: string) (diags: FSharpDiagnostic[]) = + let errors = diags |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) + let msgs = distinctDiags errors |> Array.map snd + if not (msgs |> Array.exists (fun m -> m.Contains text)) then + failwithf "Expected an ERROR diagnostic containing %A, but got %d:\n%s" text diags.Length (closureDump diags) + +let private assertClosureContainsAll (parts: string list) (diags: FSharpDiagnostic[]) = + let errors = diags |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) + let msgs = distinctDiags errors |> Array.map snd + if not (msgs |> Array.exists (fun m -> parts |> List.forall (fun p -> m.Contains p))) then + failwithf "Expected a single ERROR diagnostic containing all of %A, but got %d:\n%s" parts diags.Length (closureDump diags) + +let private assertClosureWarningContains (text: string) (diags: FSharpDiagnostic[]) = + let warnings = diags |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Warning) + let msgs = distinctDiags warnings |> Array.map snd + if not (msgs |> Array.exists (fun m -> m.Contains text)) then + failwithf "Expected a WARNING containing %A, but got %d diagnostic(s):\n%s" text diags.Length (closureDump diags) + +let private assertClosureExactlyOneContaining (text: string) (diags: FSharpDiagnostic[]) = + let matching = distinctDiags diags |> Array.filter (fun (_, m) -> m.Contains text) + if matching.Length <> 1 then + failwithf "Expected exactly one diagnostic containing %A, but %d of %d matched:\n%s" + text matching.Length diags.Length (closureDump diags) + +let private fooFs = "namespace Namespace\ntype Foo = \n static member public Property = 0\n" +let private fooFsi = "namespace Namespace\ntype Foo =\n class\n static member Property : int\n end\n" +let private fooFsHidden = "namespace Namespace\ntype Foo = \n static member public HiddenProperty = 0\n static member public Property = 0\n" +let private myNamespaceFs = "namespace MyNamespace\n module MyModule =\n let x = 1\n" + +[] +let ``Squiggles.ShowInFsxFiles`` () = + let _, checkResults = getParseAndCheckResults "open Thing1.Thing2" + assertDiagnosticsContain "The namespace or module 'Thing1' is not defined" checkResults + +[] +let ``Hash.RProperSquiggleForNonExistentFile`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"NonExistent\" " + assertDiagnosticsContain "'NonExistent' was not found or is invalid" checkResults + +[] +let ``Hash.RDoesNotExist.Bug3325`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"ThisDLLDoesNotExist\" " + assertDiagnosticsContain "'ThisDLLDoesNotExist' was not found or is invalid" checkResults + +[] +let ``ExactlyOneError.Bug4861`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "//\n#r \"Nonexistent\"\n" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "Nonexistent" checkResults + +[] +let ``InvalidHashLoad.ShouldBeASquiggle.Bug3012`` () = + let diags = closure [ "Test.fsx", "\n#load \"Bar.fs\"\n" ] "Test.fsx" + assertClosureContains "Bar.fs" diags + +[] +let ``HashLoad.Added`` () = + let _, checkResults = getParseAndCheckResults "//#load \"File1.fs\"\nopen MyNamespace.MyModule\nprintfn \"%d\" x\n" + assertDiagnosticsContain "MyNamespace" checkResults + +[] +let ``HashR.Removed`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"System.Transactions.dll\"\nopen System.Transactions\n" + assertNoDiagnostics checkResults + +[] +let ``HashR.AddedIn`` () = + let _, checkResults = getParseAndCheckResults "//#r \"System.Transactions.dll\"\nopen System.Transactions\n" + assertDiagnosticsContain "'Transactions' is not defined" checkResults + +[] +let ``NoError.HashR.DllWithNoPath`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"System.Transactions.dll\"\nopen System.Transactions" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.BugDefaultReferenceFileIsAlsoResolved`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"System\"\n" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.DoubleReference`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"System\"\n#r \"System\"\n" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.ResolveFromGAC`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"CustomMarshalers\"\n" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.ResolveFromFullyQualifiedPath`` () = + let path = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll") + let _, checkResults = getParseAndCheckResultsUniqueName (sprintf "#r @\"%s\"" path) + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.RelativePath1`` () = () + +[] +let ``NoError.HashR.RelativePath2`` () = () + +[] +let ``NoError.AutomaticImportsForFsxFiles`` () = + let _, checkResults = + getParseAndCheckResults + "\nopen System\nopen System.Xml\nopen System.Drawing\nopen System.Runtime.Remoting\nopen System.Runtime.Serialization.Formatters.Soap\nopen System.Data\nopen System.Drawing\nopen System.Web\nopen System.Web.Services\nopen System.Windows.Forms" + assertNoDiagnostics checkResults + +[] +[] +[] +[] +let ``HashDirectivesAreErrors.InNonScriptFiles`` (directive: string) = + assertDiagnosticsContain "may only be used in F# script files" (checkAsFsFile directive) + +[] +let ``ScriptCanReferenceBinDirectoryOutput.Bug3151`` () = + let _, checkResults = getParseAndCheckResults "#reference @\"bin\\Debug\\testproject.exe\"\n" + assertNoDiagnostics checkResults + +[] +let ``HashReferenceAgainstNonAssemblyExe`` () = + let path = Path.Combine(Environment.GetEnvironmentVariable("windir"), "notepad.exe") + let _, checkResults = getParseAndCheckResults (sprintf "#reference @\"%s\"\n" path) + assertDiagnosticsContain "was not found or is invalid" checkResults + +[] +let ``TypeProvider.UnitsOfMeasure.SmokeTest1`` () = () + +[] +let ``ScriptClosure.TransitiveLoad1`` () = + closure + [ "File1.fs", fooFs + "Script2.fsx", "#load \"File1.fs\"\n" + "Script1.fsx", "#load \"Script2.fsx\"\nNamespace.Foo.Property\n" ] + "Script1.fsx" + |> assertClosureNoDiagnostics + +[] +let ``ScriptClosure.TransitiveLoad2`` () = + closure + [ "File1.fs", fooFs + "Script2.fsx", "#load \"File1.fs\"\n" + "Script1.fsx", "#load \"Script2.fsx\"\nNamespace.Foo.NonExistingProperty\n" ] + "Script1.fsx" + |> assertClosureExactlyOneContaining "NonExistingProperty" + +[] +let ``HashLoad.Removed`` () = + closure + [ "File1.fs", myNamespaceFs + "File2.fsx", "#load \"File1.fs\"\nopen MyNamespace.MyModule\nprintfn \"%d\" x\n" ] + "File2.fsx" + |> assertClosureNoDiagnostics + +[] +let ``NoError.ScriptClosure.TransitiveLoad16`` () = + closure + [ "ThisProject.fsx", "#nowarn \"44\"\n" + "Script1.fsx", "#load \"ThisProject.fsx\"\n[]\nlet fn x = 0\nlet y = fn 1\n" ] + "Script1.fsx" + |> assertClosureExactlyOneContaining "This construct is deprecated. x" + +[] +let ``NoError.HashLoad.Simple`` () = + closure + [ "File1.fs", myNamespaceFs + "File2.fsx", "#load \"File1.fs\"\nopen MyNamespace.MyModule\nprintfn \"%d\" x\n" ] + "File2.fsx" + |> assertClosureNoDiagnostics + +[] +let ``NoWarn.OnLoadedFile.Bug4837`` () = + closure + [ "File1.fs", "module File1Module\nlet x = System.DateTime.Now - System.DateTime.Now\nx.Add(x) |> ignore\n" + "File2.fsx", "#load \"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureNoDiagnostics + +[] +let ``ExactlyOneError.ScriptClosure.TransitiveLoad15`` () = + closure + [ "File2.fs", "namespace Namespace\ntype Type() =\n static member Property = 0\n" + "File1.fs", "#load \"File2.fs\"\nnamespace File2Namespace\n" + "Script1.fsx", "#load \"File1.fs\"\nNamespace.Type.Property\n" ] + "Script1.fsx" + |> assertClosureExactlyOneContaining "Namespace" + +[] +let ``ScriptClosure.TransitiveLoad14`` () = + closure + [ "Script2.fsx", "#load \"Script1.fsx\"\n#r \"NonExisting\"\n" + "Script1.fsx", "#load \"Script2.fsx\"\n#r \"System\"\n" ] + "Script1.fsx" + // Cyclic #load with a resolvable `#r "System"` must not squiggle; only the deliberately + // missing `#r "NonExisting"` may warn (surfaced by the transparent compiler, not the classic one). + |> Array.filter (fun d -> not (d.Message.Contains "NonExisting")) + |> assertClosureNoDiagnostics + +[] +let ``HashLoadedFileWithErrors.Bug3149`` () = + closure + [ "File1.fs", "module File1\nDogChow\n" + "File2.fsx", "#load @\"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureContains "DogChow" + +[] +let ``HashLoadedFileWithWarnings.Bug3149`` () = + closure + [ "File1.fs", "module File1Module\ntype WarningHere<'a> = static member X() = 0\nlet y = WarningHere.X\n" + "File2.fsx", "#load @\"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureWarningContains "WarningHere" + +[] +let ``HashLoadedFileWithErrors.Bug3652`` () = + closure + [ "File1.fs", "module File1\nlet a = 1 + \"\"\nlet c = new obj()\nlet b = c.foo()\n" + "File2.fsx", "#load @\"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureContainsAll [ "'string'"; "'int'" ] + +[] +[] +[] +let ``ScriptClosure.TransitiveLoad3and4`` (caseId: int) = + let member', expected = + match caseId with + | 1123 -> "Property", null + | _ -> "NonExistingProperty", "NonExistingProperty" + let files = + [ "File1.fs", fooFs + "Script2.fsx", "#load \"Script1.fsx\"\n#load \"File1.fs\"\n" + "Script1.fsx", sprintf "#load \"Script2.fsx\"\n#load \"File1.fs\"\nNamespace.Foo.%s\n" member' ] + let diags = closure files "Script1.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +[] +[] +let ``ScriptClosure.TransitiveLoad9and5`` (caseId: int) = + let member', expected = + match caseId with + | 1124 -> "Property", null + | _ -> "HiddenProperty", "HiddenProperty" + let files = + [ "File1.fsi", fooFsi + "File1.fs", fooFsHidden + "Script1.fsx", sprintf "#load \"File1.fsi\"\n#load \"File1.fs\"\nNamespace.Foo.%s\n" member' ] + let diags = closure files "Script1.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +[] +[] +[] +[] +let ``ScriptClosure.TransitiveLoad10_12_6_8`` (caseId: int) = + let member', expected = + match caseId with + | 1125 | 1127 -> "Property", null + | _ -> "HiddenProperty", "HiddenProperty" + let script1, script2 = + match caseId with + | 1125 | 1141 -> + "#load \"File1.fsi\"\n#load \"File1.fs\"\n", + sprintf "#load \"Script1.fsx\"\nNamespace.Foo.%s\n" member' + | _ -> + "#load \"File1.fs\"\n", + sprintf "#load \"File1.fsi\"\n#load \"Script1.fsx\"\nNamespace.Foo.%s\n" member' + let files = + [ "File1.fsi", fooFsi + "File1.fs", fooFsHidden + "Script1.fsx", script1 + "Script2.fsx", script2 ] + let diags = closure files "Script2.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +[] +[] +let ``ScriptClosure.TransitiveLoad11and7`` (caseId: int) = + let member', expected = + match caseId with + | 1126 -> "Property", null + | _ -> "HiddenProperty", "HiddenProperty" + let files = + [ "File1.fsi", fooFsi + "File1.fs", fooFsHidden + "Script1.fsx", "#load \"File1.fsi\"\n" + "Script2.fsx", sprintf "#load \"Script1.fsx\"\n#load \"File1.fs\"\nNamespace.Foo.%s\n" member' ] + let diags = closure files "Script2.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +let ``Fsx.SyntheticTokens`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"\"\n#reference \"\"\n#load \"\"\n#line 52\n#nowarn 72\n" + assertDiagnosticsContain "is not a valid assembly name" checkResults + assertDiagnosticsContain "is not a valid filename" checkResults + let errors = checkResults.Diagnostics |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) + Assert.Empty(errors) + +[] +[] +[] +[] +let ``Fsx.UnclosedHashReferenceOrLoad`` (source: string) = + let _, checkResults = getParseAndCheckResultsUniqueName source + assertDiagnosticsContain "End of file in string begun" checkResults diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 6193e4f73a4..d407a64cd25 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -26,7 +26,6 @@ - @@ -55,6 +54,7 @@ + @@ -84,6 +84,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs new file mode 100644 index 00000000000..be4f2aa9c08 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs @@ -0,0 +1,29 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionActivePatternsTests + +open System +open Xunit + +let private overlapSource = + String.concat + "\n" + [ "module Overlap =" + " type Parity = Even | Odd" + " let (|Even|Odd|) x = (*loc-59*)" + " if x % 0 = 0" + " then Even (*loc-60*)" + " else Odd" + " let foo (x : int) =" + " match x with" + " | Even -> 1 (*loc-61*)" + " | Odd -> 0" + " let patval = (|Even|Odd|) (*loc-61b*)" ] + +[] +[] +[] +[ 1 (*loc-61*)")>] +[] +let ``GotoDefinition.Simple.ActivePat`` (marker: string) = + assertGoToDefinitionOnLine + "let (|Even|Odd|) x = (*loc-59*)" + (markCaretAfterLeadingIdent overlapSource marker) diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs new file mode 100644 index 00000000000..406cbd1feb8 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs @@ -0,0 +1,40 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionClassesTests + +open System +open Xunit + +let private classFieldSource = + String.concat + "\n" + [ "let id77 = 0" + "type C =" + " val id77 (*loc-77*) : int" ] + +[] +let ``GotoDefinition.InsideClass.Bug3176`` () = + assertGoToDefinitionOnLine + "val id77 (*loc-77*) : int" + (markCaretAfterLeadingIdent classFieldSource "id77 (*loc-77*)") + +let private classSource = + String.concat + "\n" + [ "type Class () = (*loc-62*)" + " member c.Method () = () (*loc-63*)" + " static member Foo () = () (*loc-64*)" + "let _ =" + " let c = Class () (*loc-65*)" + " c.Method () (*loc-66*)" + " Class.Foo () (*loc-67*)" ] + +[] +let ``GotoDefinition.ObjectOriented.ClassNameDef`` () = + assertGoToDefinitionOnLine + "type Class () = (*loc-62*)" + (markCaretAfterLeadingIdent classSource " () = (*loc-62*)") + +[] +let ``GotoDefinition.ObjectOriented.ConstructorUse`` () = + assertGoToDefinitionOnLine + "type Class () = (*loc-62*)" + (markCaretAfterLeadingIdent classSource " () (*loc-65*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..336a60c908f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs @@ -0,0 +1,61 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionDiscriminatedUnionsTests + +open System +open Xunit + +let private discUnionSource = + """ + type DiscUnion = + | Alpha of string + | Beta of decimal * unit + | Gamma + + let valueX = Beta(1.0M, ())(*GotoTypeDef*) + let valueY = valueX (*GotoValDef*) + """ + +[] +let ``Value`` () = + assertGoToDefinitionOnLine + "let valueX = Beta(1.0M, ())(*GotoTypeDef*)" + (markCaretAfterLeadingIdent discUnionSource "valueX (*GotoValDef*)") + +[] +let ``DisUnionMember`` () = + assertGoToDefinitionOnLine + "| Beta of decimal * unit" + (markCaretAfterLeadingIdent discUnionSource "Beta(1.0M, ())(*GotoTypeDef*)") + +let private simpleDatatypeSource = + String.concat + "\n" + [ "type Zero = (*loc-13*)" + "let foo (_ : Zero) : 'a = failwith \"hi\" (*loc-14*)" + "type One = (*loc-16*)" + " One (*loc-15*)" + "let f (x : One) = (*loc-17*)" + " One (*loc-18*)" + "type Nat = (*loc-19*)" + " | Suc of Nat (*loc-20*)" + " | Zro (*loc-21*)" + "let rec plus m n = (*loc-23*)" + " match m with (*loc-22*)" + " | Zro -> (*loc-24*)" + " n" + " | Suc m -> (*loc-25*)" + " Suc (plus m n) (*loc-26*)" ] + +[] +[] +[] +[] +[] +[] +[] +[] +[ (*loc-24*)")>] +[ (*loc-25*)")>] +[ (*loc-25*)", "m n) (*loc-26*)")>] +[] +let ``GotoDefinition.Simple.Datatype`` (definitionLine: string) (marker: string) = + assertGoToDefinitionOnLine definitionLine (markCaretAfterLeadingIdent simpleDatatypeSource marker) diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs new file mode 100644 index 00000000000..c37c769c362 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs @@ -0,0 +1,24 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionIdentifierIslandTests + +open Xunit + +[] +[] +[] +[] +[] +[] +[] +[] +let ``GetCompleteIdTest source-only`` (source: string) (expected: string) = + assertCompleteIdentifierIsland (Option.ofObj expected) source + +[] +let ``GetCompleteIdTest.TrivialEnd`` () = + assertCompleteIdentifierIslandWithTolerate true (Some "ThisIsAnIdentifier") "let ThisIsAnIdentifier$ = ()" + assertCompleteIdentifierIslandWithTolerate false None "let ThisIsAnIdentifier$ = ()" + +[] +let ``GetCompleteIdTest.GetsUpToDot5`` () = + assertCompleteIdentifierIslandWithTolerate true (Some "Test.Moo.Foo.bar") "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" + assertCompleteIdentifierIslandWithTolerate false None "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs new file mode 100644 index 00000000000..e2d9c9f04a4 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs @@ -0,0 +1,88 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionLetBindingsTests + +open System +open Xunit + +[] +let ``PrimitiveType`` () = + let source = + """ + // Can't goto def on an int literal + let bi = 123456I""" + + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "123456I") + +[] +let ``GotoDefinition.NoIdentifierAtLocation`` () = + let useCases = + [ "let x = 1", "1" + "let x = 1.2", ".2" + "let x = \"123\"", "2" ] + + for source, marker in useCases do + assertGoToDefinitionFails (markCaretAfterLeadingIdent source marker) + +let private trivialLetSource = + String.concat + "\n" + [ "let _ =" + " let x = () (*loc-2*)" + " x (*loc-1*)" ] + +[] +let ``GotoDefinition.Simple.Binding.TrivialLetRHSToRight`` () = + assertGoToDefinitionOnLine + "let x = () (*loc-2*)" + (markCaretAfterLeadingIdent trivialLetSource " (*loc-1*)") + +[] +let ``GotoDefinition.Simple.Binding.TrivialLetLHS`` () = + assertGoToDefinitionOnLine + "let x = () (*loc-2*)" + (markCaretAfterLeadingIdent trivialLetSource "x = () (*loc-2*)") + +let private nestedSameNameSource = + String.concat + "\n" + [ "let _ =" + " let x = () (*loc-5*)" + " let x = () (*loc-3*)" + " x (*loc-4*)" ] + +[] +[] +[] +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithSameName`` (definitionLine: string) (marker: string) = + assertGoToDefinitionOnLine definitionLine (markCaretAfterLeadingIdent nestedSameNameSource marker) + +let private nestedXIsXSource = + String.concat + "\n" + [ "let _ =" + " let x = () (*loc-7*)" + " let x =" + " x (*loc-6*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithXIsX`` () = + assertGoToDefinitionOnLine + "let x = () (*loc-7*)" + (markCaretAfterLeadingIdent nestedXIsXSource "x (*loc-6*)") + +let private lotsOfFsFuncSource = + String.concat + "\n" + [ "let _ =" + " let f = () (*loc-40*)" + " let f = (*loc-41*)" + " function f -> (*loc-42*)" + " f (*loc-43*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.LotsOfFsFunc`` () = + assertGoToDefinitionOnLine + "let f = (*loc-41*)" + (markCaretAfterLeadingIdent lotsOfFsFuncSource "f = (*loc-41*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs new file mode 100644 index 00000000000..2dae75071ef --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs @@ -0,0 +1,218 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionMembersTests + +open System +open Xunit + +[] +let ``GotoDefinition.NoSourceCodeAvailable`` () = + let source = """System.String.Format("")""" + + assertGoToDefinitionIsExternal (markCaretAfterLeadingIdent source "ormat") + +let private orPatSource = + String.concat + "\n" + [ "type Nat =" + " | Suc of Nat" + " | Zro" + "let _ =" + " let f x =" + " match x with" + " | Suc x (*loc-44*)" + " | x (*loc-45*) -> " + " x" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.OrPatLeft`` () = + assertGoToDefinitionOnLine + "| Suc x (*loc-44*)" + (markCaretAfterLeadingIdent orPatSource "x (*loc-44*)") + +[] +let ``GotoDefinition.Simple.Tricky.OrPatRight`` () = + assertGoToDefinitionOnLine + "| Suc x (*loc-44*)" + (markCaretAfterLeadingIdent orPatSource "x (*loc-45*)") + +let private consPatSource = + String.concat + "\n" + [ "let _ =" + " let f xs =" + " match xs with" + " | x :: xs (*loc-54*)" + " when xs <> [] -> (*loc-52*)" + " x :: xs (*loc-53*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhsX`` () = + assertGoToDefinitionOnLine + "| x :: xs (*loc-54*)" + (markCaretAfterLeadingIdent consPatSource "x :: xs (*loc-53*)") + +[] +let ``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhsXs`` () = + assertGoToDefinitionOnLine + "| x :: xs (*loc-54*)" + (markCaretAfterLeadingIdent consPatSource "xs (*loc-53*)") + +let private inStringSource = + String.concat + "\n" + [ "let _ =" + " let x = 2" + " \"x(*loc-72*)\"" ] + +[] +let ``GotoDefinition.Simple.Tricky.InStringFails`` () = + assertGoToDefinitionFails (markCaretAfterLeadingIdent inStringSource "x(*loc-72*)") + +let private inMultiLineStringSource = + String.concat + "\n" + [ "let _ =" + " let x = 2" + " \"this is a string" + " x(*loc-73*)" + " \"" ] + +[] +let ``GotoDefinition.Simple.Tricky.InMultiLineStringFails`` () = + assertGoToDefinitionFails (markCaretAfterLeadingIdent inMultiLineStringSource "x(*loc-73*)") + +[] +let ``GotoDefinition.Library.InitialTest`` () = + let source = "let _ = List.map (*loc-1*)" + + assertGoToDefinitionToExternalLine "map" (markCaretAfterLeadingIdent source "map (*loc-1*)") + +let private ooClassSource = + String.concat + "\n" + [ "type Class () = (*loc-62*)" + " member c.Method () = () (*loc-63*)" + " static member Foo () = () (*loc-64*)" + "let _ =" + " let c = Class () (*loc-65*)" + " c.Method () (*loc-66*)" + " Class.Foo () (*loc-67*)" ] + +[] +[] +[] +[] +[] +[] +let ``GotoDefinition.ObjectOriented`` (definitionLine: string) (marker: string) = + assertGoToDefinitionOnLine definitionLine (markCaretAfterLeadingIdent ooClassSource marker) + +let private ooClassPrimeSource = + String.concat + "\n" + [ "type Class () = (*loc-62*)" + " member c.Method () = () (*loc-63*)" + " static member Foo () = () (*loc-64*)" + "type Class' () =" + " member c.Method () = c.Method () (*loc-68*)" + " member c.Method1 () = c.Method2 () (*loc-69*)" + " member c.Method2 () = c.Method1 () (*loc-70*)" + " member c.Method3 () =" + " let c = Class ()" + " c.Method () (*loc-71*)" ] + +[] +[] +[] +[] +[] +let ``GotoDefinition.ObjectOriented.Prime`` (definitionLine: string) (marker: string) = + assertGoToDefinitionOnLine definitionLine (markCaretAfterLeadingIdent ooClassPrimeSource marker) + +let private overloadedPropertiesSource = + String.concat + "\n" + [ "type D() =" + " member this.Foo (*loc-d1*)" + " with get(i:int) = 1" + " and set (i:int) v = ()" + "" + " member this.Foo (*loc-d3*)" + " with get (s:string) = 1" + " and set (s:string) v = ()" + "" + "D().Foo 1 (*loc-u1*)" + "D().Foo 1 <- 2 (*loc-u2*)" + "D().Foo \"abc\" (*loc-u3*)" + "D().Foo \"abc\" <- 2 (*loc-u4*)" ] + +[] +let ``GotoDefinition.OverloadResolutionForProperties`` () = + assertGoToDefinitionOnLine + "member this.Foo (*loc-d1*)" + (markCaretAfterLeadingIdent overloadedPropertiesSource "Foo 1 (*loc-u1*)") + + assertGoToDefinitionOnLine + "member this.Foo (*loc-d1*)" + (markCaretAfterLeadingIdent overloadedPropertiesSource "Foo 1 <- 2 (*loc-u2*)") + + assertGoToDefinitionOnLine + "member this.Foo (*loc-d3*)" + (markCaretAfterLeadingIdent overloadedPropertiesSource "Foo \"abc\" (*loc-u3*)") + + assertGoToDefinitionOnLine + "member this.Foo (*loc-d3*)" + (markCaretAfterLeadingIdent overloadedPropertiesSource "Foo \"abc\" <- 2 (*loc-u4*)") + +let private overloadedMethodsSource = + String.concat + "\n" + [ "[]" + "type Base<'T>() =" + " member this.Method() = () (*loc-d2*)" + " abstract Method : 'T -> unit" + "" + "type Derived() =" + " inherit Base()" + "" + " override this.Method (i:int) = () (*loc-d1*)" + "" + "let d = new Derived()" + "d.Method 12 (*loc-u1*)" + "d.Method() (*loc-u2*)" ] + +[] +let ``GotoDefinition.OverloadResolutionWithOverrides`` () = + assertGoToDefinitionOnLine + "override this.Method (i:int) = () (*loc-d1*)" + (markCaretAfterLeadingIdent overloadedMethodsSource "Method 12 (*loc-u1*)") + + assertGoToDefinitionOnLine + "member this.Method() = () (*loc-d2*)" + (markCaretAfterLeadingIdent overloadedMethodsSource "Method() (*loc-u2*)") + +let private inheritedMembersSource = + String.concat + "\n" + [ "[]" + "type Foo() =" + " abstract Method : unit -> unit" + " abstract Property : int" + "type Bar() =" + " inherit Foo()" + " override this.Method () = ()" + " override this.Property = 1" + "let b = Bar()" + "b.Method(*loc-1*)()" + "b.Property(*loc-2*)" ] + +[] +let ``GotoDefinition.InheritedMembers`` () = + assertGoToDefinitionOnLine + "override this.Method () = ()" + (markCaretAfterLeadingIdent inheritedMembersSource "Method(*loc-1*)") + + assertGoToDefinitionOnLine + "override this.Property = 1" + (markCaretAfterLeadingIdent inheritedMembersSource "Property(*loc-2*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs new file mode 100644 index 00000000000..13f393c6fd6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs @@ -0,0 +1,130 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionMiscTests + +open System +open Xunit + +let private nestedLetRecSource = + String.concat + "\n" + [ "let _ =" + " let x = ()" + " let rec x = (*loc-9*)" + " fun y -> (*loc-10*)" + " x y (*loc-8*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithXRec`` () = + assertGoToDefinitionOnLine + "let rec x = (*loc-9*)" + (markCaretAfterLeadingIdent nestedLetRecSource "x y (*loc-8*)") + +let private asPatternSource = + String.concat + "\n" + [ "let _ =" + " let foo = ()" + " let f (_ as foo) = (*loc-35*)" + " foo (*loc-36*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.AsPatLHS`` () = + assertGoToDefinitionOnLine + "let f (_ as foo) = (*loc-35*)" + (markCaretAfterLeadingIdent asPatternSource "foo) = (*loc-35*)") + +[] +let ``GotoDefinition.Simple.Tricky.AsPatRHS`` () = + assertGoToDefinitionOnLine + "let f (_ as foo) = (*loc-35*)" + (markCaretAfterLeadingIdent asPatternSource "foo (*loc-36*)") + +let private lambdaMultiBindSource = + String.concat + "\n" + [ "let _ =" + " fun x (*loc-37*)" + " x -> (*loc-38*)" + " x (*loc-39*)" ] + +[] +let ``GotoDefinition.Simple.Tricky.LambdaMultBind1`` () = + assertGoToDefinitionOnLine + "fun x (*loc-37*)" + (markCaretAfterLeadingIdent lambdaMultiBindSource "x (*loc-37*)") + +let private quotedKeywordSource = + String.concat + "\n" + [ "let _ =" + " let rec ``let`` = (*loc-74*)" + " function 0 -> 1" + " | n -> n * ``let`` (n - 1) (*loc-75*)" ] + +[] +let ``GotoDefinition.Simple.Tricky.QuotedKeyword`` () = + assertGoToDefinitionOnLine + "let rec ``let`` = (*loc-74*)" + (markCaretAfterLeadingIdent quotedKeywordSource "let`` = (*loc-74*)") + +let private structConstructorSource = + String.concat + "\n" + [ "" + "[]" + "type Astruct(x:int, y:int) =" + " []" + " val mutable a : int" + " new(a) = Astruct(a, a)" + "type AS = Astruct" + "let a1 = Astruct(0)" + "let b1 = Astruct(0, 1)" + "let c1 = Astruct()" + "let a2 = AS(0)" + "let b2 = AS(0, 1)" + "let c2 = AS()" ] + +[] +let ``GotoDefinition.ObjectOriented.StructConstructor`` () = + assertGoToDefinitionOnLine + "new(a) = Astruct(a, a)" + (markCaretAfterLeadingIdent structConstructorSource "Astruct(0)") + + assertGoToDefinitionOnLine + "type Astruct(x:int, y:int) =" + (markCaretAfterLeadingIdent structConstructorSource "Astruct(0, 1)") + + assertGoToDefinitionOnLine + "type Astruct(x:int, y:int) =" + (markCaretAfterLeadingIdent structConstructorSource "Astruct()") + + assertGoToDefinitionOnLine + "new(a) = Astruct(a, a)" + (markCaretAfterLeadingIdent structConstructorSource "AS(0)") + + assertGoToDefinitionOnLine + "type Astruct(x:int, y:int) =" + (markCaretAfterLeadingIdent structConstructorSource "AS(0, 1)") + + assertGoToDefinitionOnLine + "type Astruct(x:int, y:int) =" + (markCaretAfterLeadingIdent structConstructorSource "AS()") + +[] +let ``GotoDefinition.Abbreviation.Bug193064`` () = + let source = + """ + type X = int + let f (x:X) = x(*Marker*) """ + + assertGoToDefinitionOnLine "let f (x:X) = x(*Marker*)" (markCaretAfterLeadingIdent source "x(*Marker*)") + +[] +let ``GotoDefinition.UnitOfMeasure.Bug193064`` () = + let source = + """ + open Microsoft.FSharp.Data.UnitSystems.SI + UnitSymbols.A(*Marker*)""" + + assertGoToDefinitionToExternalLine "type A = ampere" (markCaretAfterLeadingIdent source "A(*Marker*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs new file mode 100644 index 00000000000..3ee0a1f98e1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs @@ -0,0 +1,50 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionModulesTests + +open System +open Xunit + +let private moduleDefSource = + """ + //regression test for bug 2517 + module Foo (*MarkerModuleDefinition*) = + let x = () + """ + +[] +let ``ModuleDefinition`` () = + assertGoToDefinitionOnLine + "module Foo (*MarkerModuleDefinition*) =" + (markCaretAfterLeadingIdent moduleDefSource "Foo (*MarkerModuleDefinition*)") + +let private moduleSource = + String.concat + "\n" + [ "module Too = (*loc-55*)" + " let foo = 0 (*loc-56*)" + "module Bar =" + " open Too (*loc-57*)" + "let _ = Too.foo (*loc-58*)" ] + +[] +[] +[] +[] +[] +let ``GotoDefinition.Simple.Module`` (definitionLine: string) (marker: string) = + assertGoToDefinitionOnLine definitionLine (markCaretAfterLeadingIdent moduleSource marker) + +[] +let ``GotoDefinition.Simple.Module.Open`` () = + assertGoToDefinitionOnLine + "module Too = (*loc-55*)" + (markCaretAfterLeadingIdent moduleSource "Too (*loc-57*)") + +[] +let ``ModuleName.OnDefinitionSite.Bug2517`` () = + let source = + """ + namespace GotoDefinition + module Foo(*Mark*) = + let x = ()""" + + assertGoToDefinitionOnLine "module Foo(*Mark*) =" (markCaretAfterLeadingIdent source "(*Mark*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs new file mode 100644 index 00000000000..e5ce681850d --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs @@ -0,0 +1,54 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionOperatorsTests + +open System +open Xunit + +let private isOperatorChar c = + not (isIdentChar c) && not (Char.IsWhiteSpace c) + +let private markAfterOperator (source: string) (marker: string) = + match source.IndexOf(marker, StringComparison.Ordinal) with + | -1 -> failwithf "Marker %A not found in source" marker + | i -> + let mutable j = i + + while j < source.Length && isOperatorChar source.[j] do + j <- j + 1 + + source.Insert(j, "{caret}") + +[] +let ``Operators.TopLevel`` () = + let source = + """ + let (===) a b = a = b + let _ = 1 === 2 + """ + + assertGoToDefinitionOperatorOnLine "let (===) a b = a = b" "===" (markAfterOperator source "=== 2") + +[] +let ``Operators.Member`` () = + let source = + """ + type U = U + with + static member (+++) (U, U) = U + let _ = U +++ U + """ + + assertGoToDefinitionOperatorOnLine "static member (+++) (U, U) = U" "+++" (markAfterOperator source "++ U") + +let private simpleOperatorSource = + String.concat + "\n" + [ "let _ =" + " let (+) x _ = x (*loc-12*)" + " 2 + 3 (*loc-11*)" ] + +[] +let ``GotoDefinition.Simple.Binding.Operator`` () = + assertGoToDefinitionOperatorOnLine + "let (+) x _ = x (*loc-2*)" + "+" + (markAfterOperator simpleOperatorSource "+ 3 (*loc-11*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs new file mode 100644 index 00000000000..48cae003512 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs @@ -0,0 +1,129 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionPatternMatchingTests + +open System +open Xunit + +let private nestedLetSource = + String.concat + "\n" + [ "let _ =" + " let x = ()" + " let rec x = (*loc-9*)" + " fun y -> (*loc-10*)" + " x y (*loc-8*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithXRecParam`` () = + assertGoToDefinitionOnLine + "fun y -> (*loc-10*)" + (markCaretAfterLeadingIdent nestedLetSource "y (*loc-8*)") + +let private lambdaMultiBindSource = + String.concat + "\n" + [ "let _ =" + " fun x (*loc-37*)" + " x -> (*loc-38*)" + " x (*loc-39*)" ] + +[] +let ``GotoDefinition.Simple.Tricky.LambdaMultBind2`` () = + assertGoToDefinitionOnLine + "x -> (*loc-38*)" + (markCaretAfterLeadingIdent lambdaMultiBindSource "x -> (*loc-38*)") + +[] +let ``GotoDefinition.Simple.Tricky.LambdaMultBindBody`` () = + assertGoToDefinitionOnLine + "x -> (*loc-38*)" + (markCaretAfterLeadingIdent lambdaMultiBindSource "x (*loc-39*)") + +let private functionPatternSource = + String.concat + "\n" + [ "let _ =" + " let f = () (*loc-40*)" + " let f = (*loc-41*)" + " function f -> (*loc-42*)" + " f (*loc-43*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.LotsOfFsPat`` () = + assertGoToDefinitionOnLine + "function f -> (*loc-42*)" + (markCaretAfterLeadingIdent functionPatternSource "f -> (*loc-42*)") + +[] +let ``GotoDefinition.Simple.Tricky.LotsOfFsUse`` () = + assertGoToDefinitionOnLine + "function f -> (*loc-42*)" + (markCaretAfterLeadingIdent functionPatternSource "f (*loc-43*)") + +let private andPatternSource = + String.concat + "\n" + [ "type Nat = Suc of Nat | Zro" + "let _ =" + " let f x =" + " match x with" + " | Suc y & z -> (*loc-47*)" + " y (*loc-46*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.AndPat`` () = + assertGoToDefinitionOnLine + "| Suc y & z -> (*loc-47*)" + (markCaretAfterLeadingIdent andPatternSource "y (*loc-46*)") + +let private consPatternSource = + String.concat + "\n" + [ "let _ =" + " let f xs =" + " match xs with" + " | x :: xs -> (*loc-49*)" + " x (*loc-48*)" + " | _ -> []" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.ConsPat`` () = + assertGoToDefinitionOnLine + "| x :: xs -> (*loc-49*)" + (markCaretAfterLeadingIdent consPatternSource "x (*loc-48*)") + +let private pairPatternSource = + String.concat + "\n" + [ "let _ =" + " let f x =" + " match x with" + " | (y : int, z) -> (*loc-51*)" + " y (*loc-50*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.PairPat`` () = + assertGoToDefinitionOnLine + "| (y : int, z) -> (*loc-51*)" + (markCaretAfterLeadingIdent pairPatternSource "y (*loc-50*)") + +let private consWhenSource = + String.concat + "\n" + [ "let _ =" + " let f xs =" + " match xs with" + " | x :: xs (*loc-54*)" + " when xs <> [] -> (*loc-52*)" + " x :: xs (*loc-53*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhen`` () = + assertGoToDefinitionOnLine + "| x :: xs (*loc-54*)" + (markCaretAfterLeadingIdent consWhenSource "xs <> [] -> (*loc-52*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs new file mode 100644 index 00000000000..8a62ce25c82 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs @@ -0,0 +1,27 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionRecordsTests + +open System +open Xunit + +let private simpleRecordSource = + String.concat + "\n" + [ "type MyRec = (*loc-27*)" + " { myX : int (*loc-28*)" + " myY : int (*loc-29*)" + " }" + "let rDefault =" + " { myX = 2 (*loc-30*)" + " myY = 3 (*loc-31*)" + " }" + "let _ = { rDefault with myX = 7 } (*loc-32*)" ] + +[] +[] +[] +[] +[] +[] +[] +let ``GotoDefinition.Simple.Datatype.Record`` (definitionLine: string) (marker: string) = + assertGoToDefinitionOnLine definitionLine (markCaretAfterLeadingIdent simpleRecordSource marker) diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs new file mode 100644 index 00000000000..c6855d8c6c9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs @@ -0,0 +1,188 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionTypeAnnotationsTests + +open System +open Xunit + +let private bug2516SpacedSource = + """ + //regression test for bug 2516 + type One (*Marker1*) = One + let f (x : One (*Marker2*)) = 2 + """ + +[] +let ``OnTypeDefinition`` () = + assertGoToDefinitionOnLine + "type One (*Marker1*) = One" + (markCaretAfterLeadingIdent bug2516SpacedSource "One (*Marker1*)") + +[] +let ``Parameter`` () = + assertGoToDefinitionOnLine + "type One (*Marker1*) = One" + (markCaretAfterLeadingIdent bug2516SpacedSource "One (*Marker2*)") + +let private overloadResolutionSource = + String.concat + "\n" + [ "type D() =" + " override this.ToString() (*#3#*) = System.String.Empty" + " member this.ToString(s : string) (*#4#*) = ()" + "" + " member this.Foo() (*#1#*) = ()" + " member this.Foo(x) (*#2#*) = ()" + "" + "let d = new D()" + "d.Foo() (*$1$*)" + "d.Foo(1) (*$2$*)" + "d.ToString() (*$3$*)" + "d.ToString(\"aaa\") (*$4$*)" ] + +[] +let ``GotoDefinition.OverloadResolution`` () = + assertGoToDefinitionOnLine + "member this.Foo() (*#1#*) = ()" + (markCaretAfterLeadingIdent overloadResolutionSource "Foo() (*$1$*)") + + assertGoToDefinitionOnLine + "member this.Foo(x) (*#2#*) = ()" + (markCaretAfterLeadingIdent overloadResolutionSource "Foo(1) (*$2$*)") + + assertGoToDefinitionOnLine + "override this.ToString() (*#3#*) = System.String.Empty" + (markCaretAfterLeadingIdent overloadResolutionSource "ToString() (*$3$*)") + + assertGoToDefinitionOnLine + "member this.ToString(s : string) (*#4#*) = ()" + (markCaretAfterLeadingIdent overloadResolutionSource "ToString(\"aaa\") (*$4$*)") + +let private overloadStaticsSource = + String.concat + "\n" + [ "type T =" + " static member Foo(i : int) (*#1#*) = ()" + " static member Foo(s : string) (*#2#*) = ()" + "" + "T.Foo 1 (*$1$*)" + "T.Foo \"abc\" (*$2$*)" ] + +[] +let ``GotoDefinition.OverloadResolutionStatics`` () = + assertGoToDefinitionOnLine + "static member Foo(i : int) (*#1#*) = ()" + (markCaretAfterLeadingIdent overloadStaticsSource "Foo 1 (*$1$*)") + + assertGoToDefinitionOnLine + "static member Foo(s : string) (*#2#*) = ()" + (markCaretAfterLeadingIdent overloadStaticsSource "Foo \"abc\" (*$2$*)") + +let private constructorsSource = + String.concat + "\n" + [ "type B() (*#1#*) =" + " new(i : int) (*#2#*) = B()" + " new(s : string) (*#3#*) = B()" + "" + "B()" + "B(1)" + "B(\"abc\")" + "" + "new B() (*$1b$*)" + "new B(1) (*$2b$*)" + "new B(\"abc\") (*$3b$*)" + "" + "type D1() =" + " inherit B() (*$1c$*)" + "" + "type D2() =" + " inherit B(1) (*$2c$*)" + "" + "type D3() =" + " inherit B(\"abc\") (*$3c$*)" + "" + "let o1 = { new B() (*$1d$*) with" + " override this.ToString() = \"\"" + " }" + "let o2 = { new B(1) (*$2d$*) with" + " override this.ToString() = \"\"" + " }" + "let o3 = { new B(\"aaa\") (*$3d$*) with" + " override this.ToString() = \"\"" + " }" ] + +[] +let ``GotoDefinition.Constructors`` () = + assertGoToDefinitionOnLine + "type B() (*#1#*) =" + (markCaretAfterLeadingIdent constructorsSource "B() (*$1b$*)") + + assertGoToDefinitionOnLine + "new(i : int) (*#2#*) = B()" + (markCaretAfterLeadingIdent constructorsSource "B(1) (*$2b$*)") + + assertGoToDefinitionOnLine + "new(s : string) (*#3#*) = B()" + (markCaretAfterLeadingIdent constructorsSource "B(\"abc\") (*$3b$*)") + + assertGoToDefinitionOnLine + "type B() (*#1#*) =" + (markCaretAfterLeadingIdent constructorsSource "B() (*$1c$*)") + + assertGoToDefinitionOnLine + "new(i : int) (*#2#*) = B()" + (markCaretAfterLeadingIdent constructorsSource "B(1) (*$2c$*)") + + assertGoToDefinitionOnLine + "new(s : string) (*#3#*) = B()" + (markCaretAfterLeadingIdent constructorsSource "B(\"abc\") (*$3c$*)") + + assertGoToDefinitionOnLine + "type B() (*#1#*) =" + (markCaretAfterLeadingIdent constructorsSource "B() (*$1d$*)") + + assertGoToDefinitionOnLine + "new(i : int) (*#2#*) = B()" + (markCaretAfterLeadingIdent constructorsSource "B(1) (*$2d$*)") + + assertGoToDefinitionOnLine + "new(s : string) (*#3#*) = B()" + (markCaretAfterLeadingIdent constructorsSource "B(\"aaa\") (*$3d$*)") + +let private simplePolymorphSource = + String.concat + "\n" + [ "let _ =" + " let a = 2" + " let id (x : 'a) (*loc-33*)" + " : 'a = x (*loc-34*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Polymorph.Leftmost`` () = + assertGoToDefinitionOnLine + "let id (x : 'a) (*loc-33*)" + (markCaretAfterLeadingIdent simplePolymorphSource "a) (*loc-33*)") + +[] +let ``GotoDefinition.Simple.Polymorph.NotLeftmost`` () = + assertGoToDefinitionOnLine + "let id (x : 'a) (*loc-33*)" + (markCaretAfterLeadingIdent simplePolymorphSource "a = x (*loc-34*)") + +let private bug2516ModuleSource = + """ + module GotoDefinition + type One(*Mark1*) = One + let f (x : One(*Mark2*)) = 2""" + +[] +let ``Identifier.IsConstructor.Bug2516`` () = + assertGoToDefinitionOnLine + "type One(*Mark1*) = One" + (markCaretAfterLeadingIdent bug2516ModuleSource "One(*Mark1*)") + +[] +let ``Identifier.IsTypeName.Bug2516`` () = + assertGoToDefinitionOnLine + "type One(*Mark1*) = One" + (markCaretAfterLeadingIdent bug2516ModuleSource "One(*Mark2*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs new file mode 100644 index 00000000000..9c332713123 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs @@ -0,0 +1,59 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionTypeProvidersTests + +open Xunit + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute`` () = + let targetLine = "// A0(*ColumnMarker*)1234567890" + assertGoToDefinitionOnLine targetLine + (markCaretAfterLeadingIdent "\nlet a = typeof\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " "T(*GotoValDef*)") + assertGoToDefinitionOnLine targetLine + (markCaretAfterLeadingIdent "\nlet a = typeof\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " "T``") + assertGoToDefinitionOnLine targetLine + (markCaretAfterLeadingIdent "\nlet foo = new N.T(*GotoValDef*)()\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " "T(*GotoValDef*)") + assertGoToDefinitionOnLine targetLine + (markCaretAfterLeadingIdent "\nlet t = new N.T.M(*GotoValDef*)()\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " "M(*GotoValDef*)") + assertGoToDefinitionOnLine targetLine + (markCaretAfterLeadingIdent "\nlet p = N.T.StaticProp(*GotoValDef*)\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " "StaticProp(*GotoValDef*)") + assertGoToDefinitionOnLine targetLine + (markCaretAfterLeadingIdent "\nlet t = new N.T()\nt.Event1(*GotoValDef*)\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " "Event1(*GotoValDef*)") + +[] +let ``GotoDefinition.ProvidedTypeNoDefinitionLocationAttribute`` () = + let source = "\ntype T = N1.T<\"\", 1>\n" + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "T<") + +[] +let ``GotoDefinition.ProvidedMemberNoDefinitionLocationAttribute`` () = + assertGoToDefinitionFails (markCaretAfterLeadingIdent "\ntype T = N1.T<\"\", 1>\nT.Param1\n" "ram1") + assertGoToDefinitionFails (markCaretAfterLeadingIdent "\ntype T = N1.T1\nT.M1(1)\n" "1(") + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.FileDoesnotExist`` () = + let source = "\nlet a = typeof\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "T(*GotoValDef*)") + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.LineDoesnotExist`` () = + let source = "\nlet a = typeof\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "T(*GotoValDef*)") + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Constructor.FileDoesnotExist`` () = + let source = "\nlet foo = new N.T(*GotoValDef*)()\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "T(*GotoValDef*)") + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Method.FileDoesnotExist`` () = + let source = "\nlet t = new N.T.M(*GotoValDef*)()\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "M(*GotoValDef*)") + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Property.FileDoesnotExist`` () = + let source = "\nlet p = N.T.StaticProp(*GotoValDef*)\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "StaticProp(*GotoValDef*)") + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Event.FileDoesnotExist`` () = + let source = "\nlet t = new N.T()\nt.Event1(*GotoValDef*)\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails (markCaretAfterLeadingIdent source "Event1(*GotoValDef*)") diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs new file mode 100644 index 00000000000..1b2e98dfd0a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoAttributesTests + +open Xunit + +[] +let ``Single.OnAttributes`` () = + assertParameterInfoOverloads [ []; [ "check: bool" ] ] """ +type Emp = + [] + static val mutable private m_ID : int""" + +[] +let ``LocationOfParams.Attributes.Bug230393`` () = + assertHasParameterInfo """ +let paramTest((strA : string),(strB : string)) = + strA + strB +param{caret}Test( + +[] +type RMB""" + +[] +let ``ParameterInfo.ArgumentsWithParamsArrayAttribute`` () = + assertParameterInfoContains [ "format"; "[] args" ] """let _ = System.String.Form{caret}at("",)""" + +[] +let ``Regression.Multi.ExplicitAnnotate.Bug93188`` () = + assertParameterInfoOverloads [ ["int"; "string"] ] """ +type LiveAnimalAttribute(a : int, b: string) = + inherit System.Attribute() + +[] +type Wombat() = class end""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs new file mode 100644 index 00000000000..b952444ce85 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs @@ -0,0 +1,27 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoByrefSpansTests + +open Xunit + +[] +let ``Single.DotNet.ParameterByReference`` () = + assertParameterInfoOverloads [ ["s: string"; "result: int byref"]; ["s"; "style"; "provider"; "result"] ] """ +let s = "1" +let _ = System.Int32.TryParse(s,{caret}""" + +[] +let ``Single.Locations.OperatorTrick3`` () = + assertHasParameterInfo """ +open System.Threading +let mutable n = null +let aaa = Interlocked.Excha{caret}nge(&n, new obj())""" + +let multiGenericExchangeCases: obj[] seq = + [ + [| box [ "byref"; "int" ]; box "System.Threading.Interlocked.Excha{caret}nge(123," |] + [| box [ "byref"; "float" ]; box "System.Threading.Interlocked.Excha{caret}nge(12.0," |] + [| box [ "byref"; "obj" ]; box "System.Threading.Interlocked.Excha{caret}nge<_> (obj," |] + ] + +[] +let ``Multi.Generic.Exchange`` (expected: string list) (source: string) = + assertParameterInfoContains expected source diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs new file mode 100644 index 00000000000..a0e5c77c252 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs @@ -0,0 +1,52 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoClassesTests + +open Xunit + +[] +let ``Regression.OnConstructor.881644`` () = + assertParameterInfoContains ["path: string"] "new System.IO.StreamReader({caret}" + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_3`` () = + assertFirstReturnTypeText ": unit" """ +type M() = + member this.f x = () +let m = new M() +m.f({caret}""" + +[] +let ``Single.Constructor1`` () = + assertHasParameterInfo "new System.DateTime({caret}" + +[] +let ``LocationOfParams.InsideAMemberOfAType`` () = + assertHasParameterInfo """ +type Widget(z) = + member x.a = (1 <> System.Int32.Pa{caret}rse("")) """ + +[] +let ``Multi.DotNet.StaticMethod.WithinClassMember`` () = + assertParameterInfoContains ["string"; "System.Globalization.NumberStyles"] """ +type Widget(z) = + member x.a = (1 <> System.Int32.Pa{caret}rse("", + +let widget = Widget(1) +45""" + +[] +let ``Multi.DotNet.Constructor`` () = + assertParameterInfoContains ["int"; "int"; "int"] "let _ = new System.Date{caret}Time(2010,12," + +[] +let ``Regression.OptionalArguments.Bug4042`` () = + assertParameterInfoOverloads [ ["x: int"; "?y int"] ] """ +module ParameterInfo +type TT(x : int, ?y : int) = + let z = y + do printfn "%A" z + member this.Foo(?z : int) = z + +type TT2(x : int, y : int option) = + let z = y + do printfn "%A" z +let tt = TT({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs new file mode 100644 index 00000000000..bfe63538e96 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs @@ -0,0 +1,20 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoComputationExpressionsTests + +open Xunit + +[] +let ``Regression.InsideWorkflow.6437`` () = + assertParameterInfoContains ["count: int"] """ +open System.IO +let computation2 = + async { use file = File.Open("",FileMode.Open) + let! buffer = file.AsyncRead({caret}0) + return 0 }""" + +[] +let ``Regression.ParameterFirstTypeOpenParen.Bug90798`` () = + assertParameterInfoOverloads [ ["'Arg -> Async<'T>"] ] """ +let a = async { + Async.AsBeginEnd({caret} + } +let p = 10""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..ce393a2b138 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs @@ -0,0 +1,24 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoDiscriminatedUnionsTests + +open Xunit + +[] +let ``Single.DiscriminatedUnion.Construction`` () = + let du = """ +type MyDU = + | Case1 of int * string + | Case2 of V1 : int * string * V3 : bool + | Case3 of ``Long Name`` : int * Item2 : string + | Case4 of int +""" + assertParameterInfoOverloads [ ["int"; "string"] ] (du + "let x1 = Case1({caret}") + assertParameterInfoOverloads [ ["V1: int"; "string"; "V3: bool"] ] (du + "let x2 = Case2({caret}") + assertParameterInfoOverloads [ ["``Long Name`` : int"; "string"] ] (du + "let x3 = Case3({caret}") + assertParameterInfoOverloads [ ["int"] ] (du + "let x4 = Case4({caret}") + +[] +let ``LocationOfParams.Unions1`` () = + assertHasParameterInfo """ +type MyDU = + | FOO of int * string +let r = F{caret}OO(42,"") """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs new file mode 100644 index 00000000000..33bdc52c3ca --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs @@ -0,0 +1,15 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoEventsTests + +open Xunit + +[] +let ``Single.Generics.EventHandler`` () = + assertParameterInfoOverloads [ [""] ] "open System\nnew System.EventHandler( {caret}" + +[] +let ``Single.Generics.EventHandlerEventArgs`` () = + assertParameterInfoOverloads [ [""] ] "open System\nSystem.EventHandler({caret}" + +[] +let ``Single.Generics.EventHandlerEventArgsNew`` () = + assertParameterInfoOverloads [ [""] ] "open System\nnew System.EventHandler ( {caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs new file mode 100644 index 00000000000..f7138f26431 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs @@ -0,0 +1,14 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoExceptionsTests + +open Xunit + +[] +let ``Single.Exception.Construction`` () = + let exns = """ +exception E1 of int * string +exception E2 of V1 : int * string * V3 : bool +exception E3 of ``Long Name`` : int * Data1 : string +""" + assertParameterInfoOverloads [ ["int"; "string"] ] (exns + "let x1 = E1({caret}") + assertParameterInfoOverloads [ ["V1: int"; "string"; "V3: bool"] ] (exns + "let x2 = E2({caret}") + assertParameterInfoOverloads [ ["``Long Name`` : int"; "string"] ] (exns + "let x3 = E3({caret}") diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs new file mode 100644 index 00000000000..3c1abfb9432 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs @@ -0,0 +1,32 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoFunctionsTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_5`` () = + assertFirstReturnTypeText ": (int -> int) " """ + let f x y = x + y + f({caret}""" + +[] +let ``Single.BasicFSharpFunction`` () = + assertParameterInfoOverloads [["x: 'a"]] """ + let foo(x) = 1 + foo({caret}""" + +[] +let ``Single.Locations.FunctionWithSpace`` () = + assertHasParameterInfo "let a = sin 0{caret}.0" + +[] +let ``LocationOfParams.ThisOnceAssertedToo`` () = + assertNoParameterInfo """ + let readString() = + let x = 42 + while ('"' = '""' then + () + else + let sb = new System.Text.StringBuilder() + while true do + ({caret}) """ + diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs new file mode 100644 index 00000000000..1dc982aa032 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs @@ -0,0 +1,106 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoGenericsTests + +open Xunit + +[] +let ``Single.Generics.Typeof`` () = + assertNoParameterInfo "typeof({caret}" + +[] +let ``Single.Generics.MathAbs`` () = + assertParameterInfoOverloads (List.replicate 7 ["value"]) """ +open System +Math.Abs({caret}""" + +[] +let ``Single.Generics.ExchangeInt`` () = + assertParameterInfoOverloads (List.replicate 7 ["location1"; "value"]) """ +open System.Threading +Interlocked.Exchange({caret}""" + +[] +let ``Single.Generics.Exchange`` () = + assertParameterInfoOverloads (List.replicate 7 ["location1"; "value"]) """ +open System.Threading +Interlocked.Exchange({caret}""" + +[] +let ``Single.Generics.ExchangeUnder`` () = + assertParameterInfoOverloads (List.replicate 7 ["location1"; "value"]) """ +open System.Threading +Interlocked.Exchange<_> ({caret}""" + +[] +let ``Single.Generics.Dictionary`` () = + assertParameterInfoOverloads [ []; ["capacity"]; ["comparer"]; ["capacity"; "comparer"]; ["dictionary"]; ["dictionary"; "comparer"] ] """ +System.Collections.Generic.Dictionary<_, option>({caret}""" + +[] +let ``Single.Generics.List`` () = + assertParameterInfoOverloads [ []; ["capacity"]; ["collection"] ] """ +new System.Collections.Generic.List< _ > ( {caret}""" + +[] +let ``Single.Generics.ListInt`` () = + assertParameterInfoOverloads [ []; ["capacity"]; ["collection"] ] """ +System.Collections.Generic.List({caret}""" + +[] +let ``Single.Locations.GenericCtorWithNamespace`` () = + assertHasParameterInfo "let _ = new System.Collections.Generic.Dictionary<_, _>({caret})" + +[] +let ``Single.Locations.GenericCtor`` () = + assertHasParameterInfo """ +open System.Collections.Generic +let _ = new Dictionary<_, _>({caret})""" + +[] +let ``Single.Locations.Multiline.IdentOnPrevLineWithGenerics`` () = + assertHasParameterInfo """ +open System.Collections.Generic +let d = Dictionar{caret}y<_, option< int >> + ( )""" + +[] +let ``Single.Locations.GenericCtorWithoutNew`` () = + assertHasParameterInfo "let d = System.Collections.Generic.Dictionar{caret}y<_, option< int >> ( )" + +[] +let ``Single.Locations.Multiline.GenericTyargsOnTheSameLine`` () = + assertHasParameterInfo "let dict3 = System.Collections.Generic.Dictionar{caret}y<_, \n option< int>>( )" + +[] +let ``ParameterInfo.LocationOfParams.Bug112340`` () = + assertHasParameterInfo """let a = typeof] +let ``LocationOfParams.Generics1`` () = + assertHasParameterInfo """ + let f<'T,'U>(x:'T, y:'U) = (y,x) + let r = f{caret}(42,"")""" + +[] +let ``LocationOfParams.Generics2`` () = + assertHasParameterInfo """let x = System.Collections.Generic.Dictionar{caret}y(42,null)""" + +[] +let ``LocationOfParams.EvenWhenOverloadResolutionFails.Case2`` () = + assertHasParameterInfo """ + open System.Collections.Generic + open System.Linq + let l = List([||]) + l.Aggregate({caret}) // was once a bug""" + +[] +let ``Multi.Generic.Dictionary`` () = + assertParameterInfoContains ["int"; "System.Collections.Generic.IEqualityComparer"] "System.Collections.Generic.Dictionar{caret}y<_, option>(12," + +[] +let ``Multi.Generic.HashSet`` () = + assertParameterInfoContains ["Seq<'a>"; "System.Collections.Generic.IEqualityComparer<'a>"] "System.Collections.Generic.HashSet({ 1 ..12 },{caret}" + +[] +let ``Multi.Generic.SortedList`` () = + assertParameterInfoContains ["int"; "System.Collections.Generic.IComparer<'TKey>"] "System.Collections.Generic.SortedList<_,option> (12,{caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs new file mode 100644 index 00000000000..14ae2220e84 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoIndexingSlicingTests + +open Xunit + +[] +let ``Single.DotNet.IndexerParameter`` () = + assertParameterInfoOverloads [ ["index: int"] ] """ +let alist = System.Collections.ArrayList(2) +alist.[{caret}0] |> ignore""" + +[] +let ``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Open`` () = + assertHasParameterInfo """ +let arr = Array.create 4 1 +arr.[1] <- System.Int32.Parse({caret} +open System""" + +[] +let ``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Module`` () = + assertHasParameterInfo """ +let arr = Array.create 4 1 +arr.[1] <- System.Int32.Parse({caret} +module Foo = + let x = 42""" + +[] +let ``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Namespace`` () = + assertHasParameterInfo """ +namespace Foo +module Bar = + let arr = Array.create 4 1 + arr.[1] <- System.Int32.Parse({caret} +namespace Other""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs new file mode 100644 index 00000000000..c44cd07abce --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs @@ -0,0 +1,12 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoInterfacesTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_2`` () = + assertFirstReturnTypeText ": int" """ +type IFoo = interface + abstract f : int -> int + end +let i : IFoo = null +i.f({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs new file mode 100644 index 00000000000..1caebc2db94 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs @@ -0,0 +1,15 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoLambdasTests + +open Xunit + +[] +let ``Regression.LocationOfParams.Bug91479`` () = + assertHasParameterInfo "let z = fun x -> x + System.Int16.Parse({caret} " + +[] +let ``Multi.DotNet.StaticMethod.WithinLambda`` () = + assertParameterInfoContains ["string"; "System.Globalization.NumberStyles"] """let z = fun x -> x + System.Int16.Parse("",{caret}""" + +[] +let ``Multi.DotNet.StaticMethod.WithinLambda2`` () = + assertParameterInfoOverloads [ ["fileName: string"] ] "let _ = fun file -> new System.IO.FileInfo({caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs new file mode 100644 index 00000000000..581cdb04feb --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs @@ -0,0 +1,11 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoLetBindingsTests + +open Xunit + +[] +let ``Single.InString`` () = + assertNoParameterInfo """let s = "System.Console.WriteLine({caret})" """ + +[] +let ``Multi.NoParameterInfo.WithinString`` () = + assertNoParameterInfo """let s = "new System.DateTime(2000,12{caret}" """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs new file mode 100644 index 00000000000..752c63474dc --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs @@ -0,0 +1,144 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoMembersTests + +open Xunit + +[] +let ``Regression.MethodInfo.Bug808310`` () = + assertHasParameterInfo "System.Console.WriteLine({caret}" + +[] +let ``Single.DotNet.StaticMethod`` () = + assertParameterInfoOverloads [["objA"; "objB"]] "System.Object.ReferenceEquals({caret}" + +[] +let ``Regression.NoParameterInfo.100I.Bug5038`` () = + assertNoParameterInfo "100I({caret}" + +[] +let ``Single.DotNet.InstanceMethod`` () = + assertParameterInfoOverloads [["startIndex: int"]; ["startIndex: int"; "length: int"]] """ +let s = "Hello" +s.Substring({caret}""" + +[] +let ``Single.DotNet.NoParameters`` () = + assertParameterInfoOverloads [[]] """ +let x = "a" +x.ToUpperInvariant({caret}""" + +[] +let ``Single.DotNet.OnSecondParameter`` () = + assertHasParameterInfo "System.String.Format(\"x\",{caret}" + +[] +let ``Single.Locations.PointOfDefinition`` () = + assertNoParameterInfo """ +type FunkyType = + private new({caret}) = {}""" + +[] +let ``Single.Locations.AfterTypeAnnotation`` () = + assertNoParameterInfo """ +type Emp = + val mutable private m_DoB : System.DateTime + {caret}""" + +[] +let ``Single.Locations.AfterValues`` () = + assertNoParameterInfo "let _ = <@@ let x = 1 in x{caret} @@>" + +[] +let ``Single.Locations.EndOfFile`` () = + assertParameterInfoOverloads [[]] "System.Console.ReadLine({caret}" + +[] +let ``Single.QuotedIdentifier`` () = + assertParameterInfoOverloads [[]; ["maxValue: int"]; ["minValue: int"; "maxValue: int"]] """ +let ``Random Number Generator`` = System.Random() +let ``?Max!Value?`` = 100 +let _ = ``Random Number Generator``.Next({caret}``?Max!Value?``)""" + +[] +let ``Single.Locations.LineWithSpaces`` () = + assertHasParameterInfo """ +let r = + System.Math.Abs({caret}0)""" + +[] +let ``Single.Locations.FullCall`` () = + assertHasParameterInfo "System.Math.Abs({caret}0)" + +[] +let ``Single.Locations.SpacesAfterParen`` () = + assertHasParameterInfo """ +open System +let a = Math.Sign({caret}-10 )""" + +[] +let ``Single.Locations.MethodCallWithoutParens`` () = + assertHasParameterInfo """ +open System +let n = Math.Sin 1{caret}0.0""" + +[] +let ``Single.Locations.Multiline.IdentOnPrevPrevLine`` () = + assertHasParameterInfo """ +open System +do Console.WriteLine + ({caret} + "Multiline")""" + +[] +let ``Single.Locations.Multiline.LongIdentSplit`` () = + assertHasParameterInfo """ +let ll = new System.Collections. + Generic.List< _ > ({caret})""" + +[] +let ``Single.InComment`` () = + assertNoParameterInfo "// System.Console.WriteLine({caret})" + +[] +let ``LocationOfParams.Case1`` () = + assertHasParameterInfo "System.Console.WriteLine({caret}\"hello\")" + +[] +let ``LocationOfParams.Case3`` () = + assertHasParameterInfo """System.Console.WriteLine + ({caret} + "hello {0}" , + "Brian" ) """ + +[] +let ``LocationOfParams.InsideObjectExpression`` () = + assertHasParameterInfo "let _ = { new System.Object({caret}) with member _.GetHashCode() = 2}" + +[] +let ``LocationOfParams.Nested1`` () = + assertHasParameterInfo "System.Console.WriteLine(\"hello {0}\" , sin ({caret}42.0 ) )" + +[] +let ``LocationOfParams.EvenWhenOverloadResolutionFails.Case1`` () = + assertHasParameterInfo "let a = new System.IO.FileStream({caret})" + +[] +let ``Multi.DotNet.InstanceMethod`` () = + assertParameterInfoContains ["startIndex: int"; "length: int"] """ +let s = "Hello" +s.Substring({caret}0,1)""" + +[] +let ``Multi.OverloadMethod.OrderedParameters`` () = + assertParameterInfoContains ["year: int"; "month: int"; "day: int"] "new System.DateTime({caret}2000,12,1)" + +[] +let ``ParameterInfo.Multi.NoParameterInfo.InComments`` () = + assertNoParameterInfo "//let _ = System.Object({caret})" + +[] +let ``Multi.NoParameterInfo.InComments2`` () = + assertNoParameterInfo "(*System.Console.WriteLine({caret}\"Test on Fsharp style comments.\")*)" + +[] +let ``BasicBehavior.DotNet.Static`` () = + assertParameterInfoContains ["string"; "obj array"] "System.String.Format({caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs new file mode 100644 index 00000000000..2d0f6c93ba6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs @@ -0,0 +1,23 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoModulesTests + +open Xunit + +[] +let ``Regression.MethodSortedByArgumentCount.Bug4495.Case1`` () = + assertParameterInfoOverloadIndex 0 ["System.Type array"] """ +module ParameterInfo + +let a1 = System.Reflection.Assembly.Load("mscorlib") +let m = a1.GetType("System.Decimal").GetConstructor({caret}null)""" + +[] +let ``Regression.MethodSortedByArgumentCount.Bug4495.Case2`` () = + assertParameterInfoContains + [ "System.Reflection.BindingFlags" + "System.Reflection.Binder" + "System.Type array" + "System.Reflection.ParameterModifier array" ] """ +module ParameterInfo + +let a1 = System.Reflection.Assembly.Load("mscorlib") +let m = a1.GetType("System.Decimal").GetConstructor({caret}null)""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs new file mode 100644 index 00000000000..85bf267f031 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs @@ -0,0 +1,11 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoNamespacesTests + +open Xunit + +[] +let ``Single.Locations.WithNamespace`` () = + assertHasParameterInfo "let a = System.Threading.Interlocked.Exchange({caret}" + +[] +let ``ParameterInfo.Locations.WithoutNamespace`` () = + assertHasParameterInfo "open System.Threading\nlet a = Interlocked.Exchange({caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs new file mode 100644 index 00000000000..f16503871c9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs @@ -0,0 +1,7 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoObjectExpressionsTests + +open Xunit + +[] +let ``Multi.Constructor.WithinObjectExpression`` () = + assertParameterInfoOverloads [[]] "let _ = { new System.Object({caret}) with member _.GetHashCode() = 2}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs new file mode 100644 index 00000000000..27c93f782d0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs @@ -0,0 +1,25 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoOpenDirectivesTests + +open Xunit + +[] +let ``Single.Constructor2`` () = + assertHasParameterInfo """ +open System +new DateTime({caret}""" + +[] +let ``Regression.NoParameterInfoTriggeredByOpenBrace.Bug3878`` () = + assertParameterInfoContains ["value: string"] """ +module ParameterInfo +let x = 1 + 2 + +let _ = System.Console.WriteLin{caret}e () + +let y = 1""" + +[] +let ``BasicBehavior.WithReference`` () = + assertParameterInfoContains ["System.Type"; "System.Uri []"] """ +open System.ServiceModel +let serviceHost = new ServiceHost({caret})""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs new file mode 100644 index 00000000000..8593314a65d --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs @@ -0,0 +1,23 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoOperatorsTests + +open Xunit + +[) operator group; the negative case was editor-layer only")>] +let ``Single.Negative.OperatorTrick1`` () = + assertNoParameterInfo "let fooo = 0\n >({caret} 1 )" + +[] +let ``Single.Negative.OperatorTrick2`` () = + assertNoParameterInfo "let fooo = 0\n <({caret} 1 )" + +[] +let ``LocationOfParams.InfixOperators.Case1`` () = + assertHasParameterInfo """System.Console.Write{caret}Line("" + "")""" + +[] +let ``LocationOfParams.InfixOperators.Case2`` () = + assertHasParameterInfo """System.Console.Write{caret}Line((+)(3)(4))""" + +[] +let ``Regression.ParameterWithOperators.Bug90832`` () = + assertParameterInfoContains ["value: string"] """System.Console.Write{caret}Line("This is a" + " bug.")""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs new file mode 100644 index 00000000000..96684a8a41b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs @@ -0,0 +1,53 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoPatternMatchingTests + +open Xunit + +[] +let ``Single.InMatchClause`` () = + assertParameterInfoOverloads + [ ["format"; "arg0"] + ["format"; "args"] + ["provider"; "format"; "args"] + ["format"; "arg0"; "arg1"] + ["format"; "arg0"; "arg1"; "arg2"] + ["provider"; "format"; "arg0"] + ["provider"; "format"; "arg0"; "arg1"] + ["provider"; "format"; "arg0"; "arg1"; "arg2"] ] """ +let rec f l = + match l with + | [] -> System.String.Format({caret} + | x :: xs -> f xs""" + +[] +let ``LocationOfParams.MatchGuard`` () = + assertHasParameterInfo """match [1] with | [x] when box({caret}x) <> null -> ()""" + +[] +let ``LocationOfParams.ThisOnceAsserted`` () = + assertNoParameterInfo """ +module CSVTypeProvider + +f(fun x -> + match args with + | [| y |] -> + for name, kind in (headerNames, + rowType.AddMember(new ProvidedProperty({caret} + null + | _ -> failwith "unexpected generic params" )""" + +[] +let ``Multi.MethodInMatchCause`` () = + assertParameterInfoContains ["format"; "arg0"] """ +let rec f l = + match l with + | [] -> System.String.For{caret}mat("{0:X2}", + | x :: xs -> f xs""" + +[] +let ``Regression.Multi.IndexerProperty.Bug93945`` () = + assertParameterInfoOverloads [["int"; "int"]] """ +type Year2(year : int) = + member this.Item (month : int, day : int) = month + day + +let O'seven = new Year2(2007) +let randomDay = O'seven.[12,{caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs new file mode 100644 index 00000000000..12ac004a070 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs @@ -0,0 +1,45 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoPropertiesTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_1`` () = + assertFirstReturnTypeText ": int" """ +type T() = + member this.X + with set ((a:int), (b:int)) (c:int) = () +((new T()).X({caret}""" + +[] +let ``Single.Locations.AfterProperties`` () = + assertNoParameterInfo "System.DateTime.Today{caret}" + +let private propertyGetterSetterSource = """ +type Widget(z) = + member x.P1 + with get() = System.Int32.Parse("") + and set(z) = System.Int32.Parse("") |> ignore + member x.P2 with get() = System.Int32.Parse("") + member x.P2 with set(z) = System.Int32.Parse("") |> ignore""" + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case1`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "with get() = System.Int32.Pa") + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case2`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "and set(z) = System.Int32.Pa") + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case3`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "P2 with get() = System.Int32.Pa") + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case4`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "P2 with set(z) = System.Int32.Pa") + +[] +let ``Multi.NoParameterInfo.OnProperty`` () = + assertNoParameterInfo """ +let s = "Hello" +let _ = s.Length{caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs new file mode 100644 index 00000000000..20c3ccbaf8c --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs @@ -0,0 +1,85 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoQueriesTests + +open Xunit + +[] +let ``LocationOfParams.UnmatchedParensBeforeModuleKeyword.Bug245850.Case2a`` () = + assertHasParameterInfo """ +module Repro = + query { for a in System.Int16.TryParse({caret} +module AA = + let x = 10""" + +[] +let ``Query.InNestedQuery`` () = + assertParameterInfoContains ["obj"] """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let tp = (2,3,6) +let foo = + query { + for n in numbers do + yield (n, query {for x in tuples do + let r = x.Equals({caret}tp) + select r }) + }""" + +[] +let ``Query.WithErrors`` () = + assertParameterInfoContains ["obj"] """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let tp = (2,3,6) +let foo = + query { + for t in tuples do + orderBy (t.Equals({caret}tp)) + }""" + +[] +let ``Query.OperatorWithParentheses`` () = + assertParameterInfoContains [] """ +let categories = ["Beverages"; "Condiments"; "Vegetables";] +let products = [1;2;3] +let q2 = + query { + for c in categories do + groupJoin({caret}for p in products -> c = p) into ps + select (c, ps) + } |> Seq.toArray""" + +[] +let ``Query.OptionalArgumentsInQuery`` () = + assertParameterInfoContains ["x: int"; "?y int"] """ +type TT(x : int, ?y : int) = + let z = y + do printfn "%A" z + member this.Foo(?z : int) = z + +type TT2(x : int, y : int option) = + let z = y + do printfn "%A" z +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] + +let test3 = + query { + for n in numbers do + let tt = TT({caret} + minBy n + }""" + +[] +let ``Query.OverloadMethod.InQuery`` () = + assertParameterInfoContains ["int"; "int"; "string"; "bool"] """ +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] + +type Foo() = + member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () + member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () + +let test3 = + query { + for n in numbers do + let foo = new Foo() + foo.A1(1,1,{caret} + minBy n + }""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs new file mode 100644 index 00000000000..87db424e587 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs @@ -0,0 +1,28 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoRecordsTests + +open Xunit + +[] +let ``Single.RecordAndUnionType`` () = + assertParameterInfoOverloads [ [ "Fruit"; "KeyValuePair" ] ] """ +type Fruit = | Apple | Banana +type KeyValuePair = { Key : int; Value : float } +let print (x : Fruit, kvp : KeyValuePair) = System.Console.WriteLine(x); System.Console.WriteLine(kvp) +pri{caret}nt (Banana, {Key = 0; Value = 0.0})""" + +[] +let ``Multi.Function.WithRecordType`` () = + assertParameterInfoOverloads [ ["int"; "Vector"] ] """ +type Vector = + { X : float; Y : float; Z : float } +let foo(x : int,v : Vector) = () +fo{caret}o(12, { X = 10.0; Y = 20.0; Z = 30.0 })""" + +[] +let ``Multi.NoParameterInfo.OnValues`` () = + assertNoParameterInfo """ +type Foo = class + val private size : int + val private path : string + new (s : int, p : string) = {size = s; path{caret} = p} +end""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs new file mode 100644 index 00000000000..ec2a091a41f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs @@ -0,0 +1,36 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoSeqListArrayExprsTests + +open Xunit + +[] +let ``Single.DotNet.ParameterArray`` () = + assertParameterInfoOverloads + [ ["format"; "args"] + ["format"; "arg0"] + ["provider"; "format"; "args"] + ["format"; "arg0"; "arg1"] + ["format"; "arg0"; "arg1"; "arg2"] ] """ +let x = "a" +System.String.Format("[{0}] for [{1}]", x.ToUpperInvariant(){caret}, x)""" + +[] +let ``ParameterInfo.LocationOfParams.Bug112688`` () = + assertNoParameterInfo """ +let f x y = () +module MailboxProcessorBasicTests = + do f 0 + 0 + {caret}let zz = 42 + for timeout in [0; 10] do + ()""" + +[] +let ``Multi.Function.AsParameter`` () = + assertParameterInfoOverloads [ ["int list"] ] """ +let isLessThanZero x = (x < 0) +let containsNegativeNumbers intList = + let filteredList = List.filter isLessThanZero intList + if List.length filteredList > 0 + then Some(filteredList) + else None +let _ = Option.get(containsNegativeNumber{caret}s [6; 20; 8; 45; 5])""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs new file mode 100644 index 00000000000..35ed13ec949 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs @@ -0,0 +1,17 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoStringsInterpolationTests + +open Xunit + +[] +let ``Single.Locations.Multiline.IdentOnPrevLine`` () = + assertHasParameterInfo """ +open System +do Console.WriteLine + ({caret}"Multiline")""" + +[] +let ``LocationOfParams.GenericMethodExplicitTypeArgs()`` () = + assertHasParameterInfo """ +type T<'a> = + static member M(x:int, y:string) = x + y.Length +let x = T.M{caret}(1, "test") """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs new file mode 100644 index 00000000000..185d3fc0efc --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs @@ -0,0 +1,145 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTuplesTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_4`` () = + assertFirstReturnTypeText ": string" """ + type T() = + member this.Foo(a,b) = "" + let t = new T() + t.Foo({caret}""" + +[] +let ``ParameterInfo.NamesOfParams`` () = + assertParameterInfoOverloads [["a: int"; "b: bool"; "c: int"; "d: int"; "?e int"]] """ +type Foo = + static member F(a:int, b:bool, c:int, d:int, ?e:int) = () +let a = 42 +Foo.F({caret}0,(a=42),d=3,?e=Some 4,c=2)""" + +[] +let ``LocationOfParams.Case2`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}"hello {0}" , "Brian" )""" + +[] +let ``LocationOfParams.Case4`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}"hello {0}" , ("tuples","don't confuse it") )""" + +[] +let ``LocationOfParams.Nested2`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}"hello {0}" , sin 42.0 )""" + +[] +let ``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case1`` () = + assertHasParameterInfo """ + type CC() = + member this.M(a,b,c,d) = a+b+c+d + let c = new CC() + c.M({caret}1,2,3, + c.M(1,2,3,4)""" + +[] +let ``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case2`` () = + assertHasParameterInfo """ + type CC() = + member this.M(a,b,c,d) = a+b+c+d + let c = new CC() + c.M({caret}1,2,3, + c.M(1,2,3,4) + c.M(1,2,3,4) + c.M(1,2,3,4)""" + +[] +let ``LocationOfParams.Tuples.Bug91360.Case1`` () = + assertHasParameterInfo """System.Console.WriteLine({caret} (42,43) ) // oops""" + +[] +let ``LocationOfParams.Tuples.Bug91360.Case2`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}(42,43) ) // oops""" + +[] +let ``LocationOfParams.InheritsClause.Bug192134`` () = + assertHasParameterInfo """ + type B(x : int) = + new(x1:int, x2: int) = new B(10) + type A() = + inherit B({caret}1,2)""" + +[] +let ``ParameterNamesInFunctionsDefinedByLetBindings`` () = + assertParameterInfoOverloads [["n1: int"]] "let foo (n1 : int) (n2 : int) = n1 + n2\nfoo({caret}" + assertParameterInfoOverloads [["n1: int"; "n2: int"]] "let foo (n1 : int, n2 : int) = n1 + n2\nfoo({caret}" + assertParameterInfoOverloads [["'a -> 'b"]] "let foo = List.map\nfoo({caret}" + assertParameterInfoOverloads [["int"]] "let foo x =\n let bar y = x + y\n bar({caret}" + assertParameterInfoOverloads [["int option"]] "let f (Some x) = x + 1\nf({caret}" + +[] +let ``Multi.DotNet.StaticMethod`` () = + assertParameterInfoContains ["format"; "arg0"] """System.Console.WriteLine({caret}"Today is {0:dd MMM yyyy}",System.DateTime.Today)""" + +[] +let ``Multi.Function.InTheClassMember`` () = + assertParameterInfoOverloads [["int"; "int"]] """ + type Foo() = + let foo1(a : int, b:int) = () + + member this.A() = + foo1({caret}1, + member this.A(a : string, b:int) = ()""" + +[] +let ``Multi.ParamAsTupleType`` () = + assertParameterInfoOverloads [["int * int"; "int"]] """ + let tuple((a : int, b : int), c : int) = a * b + c + let result = tuple({caret}(1, 2), 3)""" + +[] +let ``Multi.ParamAsCurryType`` () = + assertParameterInfoOverloads [["x: float"]] """ + let multi (x : float) (y : float) = 0 + let sum(a, b) = a + b + let rtnValue = sum(multi({caret}1.0) 3.0, 5)""" + +[] +let ``Multi.Function.WithOptionType`` () = + assertParameterInfoOverloads [["int option"; "string ref"]] """ + let foo( a : int option, b : string ref) = 0 + let _ = foo({caret}Some(12),""" + +[] +let ``Multi.Function.WithOptionType2`` () = + assertParameterInfoOverloads [["int option"; "float option"]] """ + let multi (x : float) (y : float) = x * y + let sum(a : int, b) = a + b + let options(a1 : int option, b1 : float option) = a1.ToString() + b1.ToString() + let rtnOption = options({caret}Some(sum(1, 3)), Some(multi 3.1 5.0)) """ + +[] +let ``Multi.Function.WithRefType`` () = + assertParameterInfoOverloads [["int ref"; "string ref"]] """ + let foo( a : int ref, b : string ref) = 0 + let _ = foo({caret}ref 12,""" + +[] +let ``Multi.Overload.WithSameParameterCount`` () = + assertParameterInfoOverloads [["int"; "int"; "string"; "bool"]; ["int"; "string"; "int"; "bool"]] """ + type Foo() = + member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () + member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () + let foo = new Foo() + foo.A1({caret}1,1,""" + +[] +let ``Multi.NoParameterInfo.OnFunctionDeclaration`` () = + assertNoParameterInfo "let Foo(x : int, {caret}b : string) = ()" + +[] +let ``LocationOfParams.Tuples.Bug123219`` () = + assertHasParameterInfo """ +type Expr = | Num of int +type T<'a>() = + member this.M1(a:int*string, b:'a -> unit) = () +let x = new T() + +x.M1((1,{caret} """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs new file mode 100644 index 00000000000..678d7dc5321 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs @@ -0,0 +1,53 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTypeAnnotationsTests + +open Xunit + +[] +let ``Regression.StaticVsInstance.Bug3626.Case1`` () = + assertParameterInfoOverloads [["staticReturnsInt: int"]] """ +type Foo() = + member this.Bar(instanceReturnsString:int) = "hllo" + static member Bar(staticReturnsInt:int) = 13 +let z = Foo.Bar({caret})""" + +[] +let ``Regression.StaticVsInstance.Bug3626.Case2`` () = + assertParameterInfoOverloads [["instanceReturnsString: int"]] """ +type Foo() = + member this.Bar(instanceReturnsString:int) = "hllo" + static member Bar(staticReturnsInt:int) = 13 +let Hoo = new Foo() +let y = Hoo.Bar({caret}""" + +[] +let ``NoArguments`` () = + assertParameterInfoOverloads [[]] """ +type T = + static member F() = 42 +let r1 = T.F({caret})""" + assertParameterInfoOverloads [[]] """ +type T = + static member G(x:unit) = 42 +let r2 = T.G({caret})""" + assertParameterInfoOverloads [[]] """ +let h((x:unit)) = 42 +let r3 = h({caret})""" + assertParameterInfoOverloads [[]] """ +let g() = 42 +let r4 = g({caret})""" + +[] +let ``Single.DotNet.OneParameter`` () = + assertParameterInfoOverloads [["value: int"]] "System.DateTime.Today.AddYears({caret}" + +[] +let ``Single.DotNet.RefTypeValueType`` () = + assertParameterInfoOverloads [ []; ["name: string"; "salary: float"; "dob: System.DateTime"]; ["name: string"; "dob: System.DateTime"] ] """ +type Emp = + val mutable private m_Name : string + val mutable private m_Salary : float + val mutable private m_DoB : System.DateTime + public new() = { m_Name = System.String.Empty; m_Salary = 0.0; m_DoB = System.DateTime.Today } + public new(name, salary, dob) = { m_Name = name; m_Salary = salary; m_DoB = dob } + public new(name, dob) = new Emp(name, 0.0, dob) +let _ = Emp({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs new file mode 100644 index 00000000000..a4f6c35d5a9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTypeExtensionsTests + +open Xunit + +[] +let ``ExtensionMethod.Overloads`` () = + assertParameterInfoOverloads [ ["a: string"]; ["a: int"] ] """ +module MyCode = + type A() = + member this.Method(a:string) = "" +module MyExtension = + type MyCode.A with + member this.Method(a:int) = "" + +open MyCode +open MyExtension +let foo = A() +foo.Method({caret}""" + +[] +let ``ExtensionProperty.Overloads`` () = + assertParameterInfoOverloads [ ["string"]; ["int"] ] """ +module MyCode = + type A() = + member this.Prop with get(a:string) = "" +module MyExtension = + type MyCode.A with + member this.Prop with get(a:int) = "" + +open MyCode +open MyExtension +let foo = A() +foo.Prop({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs new file mode 100644 index 00000000000..baa4303941a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs @@ -0,0 +1,154 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTypeProvidersTests + +open Xunit + +[] +let ``TypeProvider.StaticMethodWithOneParam`` () = + assertParameterInfoOverloads [["arg1"]] "let foo = N1.T1.M1({caret}" + +[] +let ``TypeProvider.StaticMethodWithMoreParam`` () = + assertParameterInfoOverloads [["arg1"; "arg2"]] "let foo = N1.T1.M2({caret}" + +[] +let ``TypeProvider.StaticMethodColonContent`` () = + assertFirstReturnTypeText ": int" "let foo = N1.T1.M2({caret}" + +[] +let ``TypeProvider.ConstructorWithNoParam`` () = + assertParameterInfoOverloadIndex 0 [] "let foo = new N1.T1({caret}" + +[] +let ``TypeProvider.ConstructorWithOneParam`` () = + assertParameterInfoOverloadIndex 1 ["arg1"] "let foo = new N1.T1({caret}" + +[] +let ``TypeProvider.ConstructorWithMoreParam`` () = + assertParameterInfoOverloadIndex 2 ["arg1"; "arg2"] "let foo = new N1.T1({caret}" + +[] +let ``TypeProvider.Type.WhenOpeningBracket`` () = + assertParameterInfoOverloads [["Param1"; "ParamIgnored"]] "type foo = N1.T<{caret}" + +[] +let ``TypeProvider.Type.AfterCloseBracket`` () = + assertNoParameterInfo "type foo = N1.T< \"Hello\", 2>{caret}" + +[] +let ``TypeProvider.Type.AfterDelimiter`` () = + assertParameterInfoContains ["Param1"; "ParamIgnored"] "type foo = N1.T<\"Hello\",{caret}" + +[] +let ``TypeProvider.Type.ParameterInfoLocation.WithNamespace`` () = + assertHasParameterInfo "type boo = N1.T<{caret}" + +[] +let ``TypeProvider.Type.ParameterInfoLocation.WithOutNamespace`` () = + assertHasParameterInfo "open N1 \ntype boo = T<{caret}" + +[] +let ``TypeProvider.Type.Negative.InString`` () = + assertNoParameterInfo "type boo = \"N1.T<{caret}\"" + +[] +let ``TypeProvider.Type.Negative.InComment`` () = + assertNoParameterInfo "// type boo = N1.T<{caret}" + +[] +let ``LocationOfParams.TypeProviders.Basic`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", 42 >""" + +[] +let ``LocationOfParams.TypeProviders.BasicNamed`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored=42 >""" + +[] +let ``LocationOfParams.TypeProviders.Prefix0`` () = + assertHasParameterInfo """ + type U = N1.T< {caret} """ + +[] +let ``LocationOfParams.TypeProviders.Prefix1`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", 42 """ + +[] +let ``LocationOfParams.TypeProviders.Prefix1Named`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored=42 """ + +[] +let ``LocationOfParams.TypeProviders.Prefix2`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", """ + +[] +let ``LocationOfParams.TypeProviders.Prefix2Named1`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored= """ + +[] +let ``LocationOfParams.TypeProviders.Prefix2Named2`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored """ + +[] +let ``LocationOfParams.TypeProviders.Negative1`` () = + assertNoParameterInfo """ + type D = System.Collections.Generic.Dictionary< in{caret}t, int >""" + +[] +let ``LocationOfParams.TypeProviders.Negative2`` () = + assertNoParameterInfo """ + type D = System.Collections.Generic.List< in{caret}t >""" + +[] +let ``LocationOfParams.TypeProviders.Negative3`` () = + assertNoParameterInfo """ + let i = 42 + let b = i< 4{caret}2""" + +[] +let ``LocationOfParams.TypeProviders.Negative4.Bug181000`` () = + assertNoParameterInfo """ + type U = N1.T< "foo", 42 >{caret} """ + +[] +let ``LocationOfParams.TypeProviders.BasicWithinExpr`` () = + assertNoParameterInfo """ + let f() = + let r = id( N1.T< "fo{caret}o", ParamIgnored=42 > ) + r """ + +[] +let ``LocationOfParams.TypeProviders.BasicWithinExpr.DoesNotInterfereWithOuterFunction`` () = + assertHasParameterInfo """ + let f() = + let r = id( N1.{caret}T< "foo", ParamIgnored=42 > ) + r """ + +[] +let ``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case1`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", 42, , >""" + +[] +let ``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case2`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", , >""" + +[] +let ``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case3`` () = + assertHasParameterInfo """ + type U = N1.T< ,{caret} >""" + +[] +let ``LocationOfParams.TypeProviders.StaticParametersAtConstructorCallSite`` () = + assertHasParameterInfo """ + let x = new N1.T< "fo{caret}o", 42 >()""" + +[] +let ``TypeProvider.FormatOfNamesOfSystemTypes`` () = + assertParameterInfoOverloads [["Param1: string"; "ParamIgnored: int"]] """type TTT = N1.T< "fo{caret}o", ParamIgnored=42 > """ diff --git a/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs b/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs index 6f4dad7a97d..845c08f109e 100644 --- a/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs @@ -128,3 +128,128 @@ let ``GetPartialLongNameEx preserves plain long identifiers`` (lineStr: string, Assert.NotEmpty pln.QualifyingIdents Assert.Equal(lastQualifier, List.last pln.QualifyingIdents) Assert.Equal("", pln.PartialIdent) + +// QuickParse.GetCompleteIdentifierIsland tolerateJustAfter line index -> (identifier, endColumn, isQuoted) option. +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``QuickParse GetCompleteIdentifierIsland`` + (tolerateJustAfter: bool) + (line: string) + (index: int) + (expectedIdent: string) + (expectedEndCol: int) + = + let actual = + match QuickParse.GetCompleteIdentifierIsland tolerateJustAfter line index with + | Some(ident, endCol, _) -> Some(ident, endCol) + | None -> None + + let expected = + if isNull expectedIdent then + None + else + Some(expectedIdent, expectedEndCol) + + Assert.Equal<(string * int) option>(expected, actual) + +[] +let ``QuickParse GetCompleteIdentifierIsland tolerates one char after a quoted identifier (legacy CheckIsland25, not enforced)`` + () + = + let actual = + match QuickParse.GetCompleteIdentifierIsland true "``Space Man``" 11 with + | Some(ident, endCol, _) -> Some(ident, endCol) + | None -> None + + Assert.Equal<(string * int) option>(Some("Man", 11), actual) + +// tuple (QualifyingIdents, PartialIdent, LastDotPos). Encoding for the [] primitives: +// quals: null -> [] (empty list); "" -> [""] (one empty qualifier); else ';'-split into a list. +// lastDot: -1 -> None; else Some lastDot. +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``QuickParse GetPartialLongNameEx`` + (line: string) + (quals: string) + (partialIdent: string) + (lastDot: int) + = + let actual = QuickParse.GetPartialLongNameEx(line, line.Length - 1) + + let expectedQuals = + if isNull quals then [] else quals.Split(';') |> List.ofArray + + let expectedLastDot = if lastDot < 0 then None else Some lastDot + let expected = (expectedQuals, partialIdent, expectedLastDot) + let actualTuple = (actual.QualifyingIdents, actual.PartialIdent, actual.LastDotPos) + Assert.Equal(expected, actualTuple) diff --git a/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs b/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs index fd6b868de08..c5c6ba78e9c 100644 --- a/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs @@ -60,3 +60,53 @@ let pi = Math.PI let expectedReferenceText = match [| flag |] |> Array.tryFind(fun f -> f = "--targetprofile:mscorlib") with | Some _ -> "net45" | _ -> "netstandard2.0" let found = options.OtherOptions |> Array.exists (fun s -> s.Contains(expectedReferenceText) && s.Contains("FSharp.Data.dll")) Assert.True(found) + +/// `SourceFiles` is exactly the single script; the fsi default-reference injection for a missing `#load` +/// is a host-layout detail (not product behaviour) and is intentionally not asserted. +/// Desktop-only: it asserts .NET Framework GAC assemblies (`System.Runtime.Remoting`/`System.Transactions`) +/// resolve, which is not possible on a .NET-Core-only host. +#if !NETCOREAPP +[] +let ``Fsx.ScriptClosure.SurfaceOrderOfHashes`` () = + let scriptSource = + String.concat "\n" + [ "#r \"System.Runtime.Remoting\"" + "#r \"System.Transactions\"" + "#load \"Load1.fs\"" + "#load \"Load2.fsx\"" ] + let tempFile = Path.Combine(Path.GetTempPath(), getTemporaryFileName () + ".fsx") + let options, _errors = + checker.GetProjectOptionsFromScript(tempFile, SourceText.ofString scriptSource) + |> Async.RunImmediate + let containsPartial (needle: string) = options.OtherOptions |> Array.exists (fun o -> o.Contains needle) + Assert.True(containsPartial "--noframework", "OtherOptions should contain --noframework") + Assert.True(containsPartial "System.Runtime.Remoting.dll", "OtherOptions should resolve System.Runtime.Remoting.dll") + Assert.True(containsPartial "System.Transactions.dll", "OtherOptions should resolve System.Transactions.dll") + Assert.Equal(1, options.SourceFiles.Length) + Assert.Equal(tempFile, options.SourceFiles.[0]) +#endif + +/// A no-crash test: the invalid meta-command filenames must be processed WITHOUT crashing the script +/// options (a single source file, the `--noframework` closure flag) without throwing — the invalid +/// references surface as non-fatal resolution diagnostics, never an assert. +[] +let ``Fsx.InvalidMetaCommandFilenames`` () = + let scriptSource = + String.concat "\n" + [ "#r @\"\"" + "#load @\"\"" + "#I @\"\"" + "#r @\"*\"" + "#load @\"*\"" + "#I @\"*\"" + "#r @\"?\"" + "#load @\"?\"" + "#I @\"?\"" + "#r @\"C:\\path\\does\\not\\exist.dll\" " ] + let tempFile = Path.Combine(Path.GetTempPath(), getTemporaryFileName () + ".fsx") + let options, _errors = + checker.GetProjectOptionsFromScript(tempFile, SourceText.ofString scriptSource) + |> Async.RunImmediate + Assert.Equal(1, options.SourceFiles.Length) + Assert.Equal(tempFile, options.SourceFiles.[0]) + Assert.Contains("--noframework", options.OtherOptions) diff --git a/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs b/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs index 4c1cea62bf6..48dd529b2af 100644 --- a/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs @@ -23,6 +23,17 @@ let tokenizeLines (lines:string[]) = let tokenizer = sourceTok.CreateLineTokenizer(line) yield n, parseLine(line, state, tokenizer) |> List.ofSeq ] +/// Scans every token of a (possibly multi-line) source using a single line tokenizer, +/// threading the lex state across embedded newlines (column index resets at each newline). +let scanTokens (defines: string list) (source: string) = + let sourceTok = FSharpSourceTokenizer(defines, Some "C:\\test.fsx", None, None) + let tokenizer = sourceTok.CreateLineTokenizer(source) + let rec loop (state: FSharpTokenizerLexState) acc = + match tokenizer.ScanToken(state) with + | Some tok, nstate -> loop nstate (tok :: acc) + | None, _ -> List.rev acc + loop FSharpTokenizerLexState.Initial [] + [] let ``Tokenizer test - simple let with string``() = let tokenizedLines = @@ -293,3 +304,163 @@ let ``Tokenizer test - optional parameters with question mark``() = printfn "actual = %A" actual printfn "expected = %A" expected actual |> Assert.shouldBeEqualWith expected (sprintf "actual and expected did not match,actual =\n%A\nexpected=\n%A\n" actual expected) + +[] +let ``Lexer.CommentsLexing.Bug1548``() = + let cm = FSharpTokenColorKind.Comment + let kw = FSharpTokenColorKind.Keyword + + // This specifies the source code to test and a collection of tokens that + // we want to find in the result (note: it doesn't have to contain every token, because + // behavior for some of them is undefined - e.g. "(* "\"*)" - what is token here? + let sources = + [ "// some comment", + [ ((0, 1), cm); ((2, 2), cm); ((3, 6), cm); ((7, 7), cm); ((8, 14), cm) ] + "// (* hello // 12345\nlet", + [ ((6, 10), cm); ((15, 19), cm); ((0, 2), kw) ] // checks 'hello', '12345' and keyword 'let' + "//- test", + [ ((0, 2), cm); ((4, 7), cm) ] // checks whether '//-' isn't treated as an operator + + // same thing for XML comments - these are treated in a different lexer branch + "/// some comment", + [ ((0, 2), cm); ((3, 3), cm); ((4, 7), cm); ((8, 8), cm); ((9, 15), cm) ] + "/// (* hello // 12345\nmember", + [ ((7, 11), cm); ((16, 20), cm); ((0, 5), kw) ] + "///- test", + [ ((0, 3), cm); ((5, 8), cm) ] + + // same thing for "////" - these are treated in a different lexer branch + "//// some comment", + [ ((0, 3), cm); ((4, 4), cm); ((5, 8), cm); ((9, 9), cm); ((10, 16), cm) ] + "//// (* hello // 12345\nlet", + [ ((8, 12), cm); ((17, 21), cm); ((0, 2), kw) ] + "////- test", + [ ((0, 4), cm); ((6, 9), cm) ] + + "(* test 123 (* 456 nested *) comments *)", + [ ((3, 6), cm); ((8, 10), cm); ((15, 17), cm); ((19, 24), cm); ((29, 36), cm) ] // checks 'test', '123', '456', 'nested', 'comments' + "(* \"with 123 \\\" *)\" string *)", + [ ((4, 7), cm); ((9, 11), cm); ((20, 25), cm) ] // checks 'with', '123', 'string' + "(* @\"with 123 \"\" *)\" string *)", + [ ((5, 8), cm); ((10, 12), cm); ((21, 26), cm) ] // checks 'with', '123', 'string' + ] + + for lineText, expected in sources do + // Lex the (possibly multi-line) source and add every lexed token's color to a dictionary + let lexed = System.Collections.Generic.Dictionary() + for tok in scanTokens [ "COMPILED"; "EDITING" ] lineText do + lexed[(tok.LeftColumn, tok.RightColumn)] <- tok.ColorClass + + // Verify that all tokens in the specified list occur in the lexed result with the right color + for pos, clr in expected do + let succ, v = lexed.TryGetValue(pos) + let found = [ for kvp in lexed -> kvp.Key, kvp.Value ] + Assert.True(succ, sprintf "Cannot find token %A at %A in %A\nFound: %A" clr pos lineText found) + Assert.True((clr = v), sprintf "Wrong color of token %A at %A in %A\nFound: %A" clr pos lineText found) + +[] +let ``TokenInfo.TriggerClasses``() = + let punct = FSharpTokenColorKind.Punctuation + let delim = FSharpTokenCharKind.Delimiter + + // Tokenize a minimal source, return the (ColorClass, CharClass, TriggerClass) of the first token + let triggerInfoOf (tokenName: string) (source: string) = + let toks = scanTokens [] source + match toks |> List.tryFind (fun t -> t.TokenName = tokenName) with + | Some t -> (t.ColorClass, t.CharClass, t.FSharpTokenTriggerClass) + | None -> + failwithf "Token %s was not produced by source %A. Tokens: %A" + tokenName source (toks |> List.map (fun t -> t.TokenName)) + + // important - tokens with specific trigger classes used to drive IntelliSense + triggerInfoOf "DOT" "a.b" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.MemberSelect) // member select for dot completions + triggerInfoOf "LPAREN" "f(x,y)" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.ParamStart ||| FSharpTokenTriggerClass.MatchBraces) // for parameter info + triggerInfoOf "COMMA" "f(x,y)" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.ParamNext) + triggerInfoOf "RPAREN" "f(x,y)" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.ParamEnd ||| FSharpTokenTriggerClass.MatchBraces) + + // matching - other cases where we expect MatchBraces + let matchBracesInfo = (punct, delim, FSharpTokenTriggerClass.MatchBraces) + triggerInfoOf "LQUOTE" "<@ 1 @>" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "LBRACK" "[ 1 ]" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "LBRACE" "{ x = 1 }" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "LBRACK_BAR" "[| 1 |]" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "RQUOTE" "<@ 1 @>" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "RBRACK" "[ 1 ]" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "RBRACE" "{ x = 1 }" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "BAR_RBRACK" "[| 1 |]" |> Assert.shouldBe matchBracesInfo + +// Each case has exactly one brace pair: left brace at the start marker, right brace at the end marker. +[] +let ``MatchingBraces.VerifyMatches``() = + let lines = + [ "" + " let x = (1, 2)//1" + " let y = ( 3 + 1 ) * 2" + " let z =" + " async {" + " return 10" + " }" + " let lst = " + " [// list_start" + " 1;2;3" + " ]//list_end" + " let arr = " + " [|" + " 1" + " 2" + " |]" + " let quote = <@(* S0 *) 1 @>(* E0 *)" + " let quoteWithNestedList = <@(* S1 *) ['x';'y';'z'](* E_L*) @>(* E1 *)" + " [< System.Serializable() >]" + " type T = class end" + " " ] + let source = String.concat "\n" lines + let linesArr = List.toArray lines + let braces = matchBraces ("MatchingBracesVerifyMatches", source) + + // Locate the START of the marker substring (0-based row/col). + let findMarker (marker: string) = + let mutable found = None + let mutable i = 0 + while found.IsNone && i < linesArr.Length do + let idx = linesArr[i].IndexOf(marker, System.StringComparison.Ordinal) + if idx >= 0 then found <- Some(i, idx) + i <- i + 1 + match found with + | Some p -> p + | None -> failwithf "Marker %A not found in source" marker + + let checkBraces startMarker endMarker (expectedSpanLen: int) = + let (startRow, startCol) = findMarker startMarker + let (endRow, endCol) = findMarker endMarker + + // exactly one matching pair has its left brace at the start marker (FCS line is 1-based) + let matching = + braces |> Array.filter (fun (l, _) -> l.StartLine = startRow + 1 && l.StartColumn = startCol) + Assert.Equal(1, matching.Length) + + let (lbrace, rbrace) = matching[0] + // left brace span: single line, starts at the start marker, expectedSpanLen columns wide + Assert.Equal(lbrace.StartLine, lbrace.EndLine) + Assert.Equal(startRow + 1, lbrace.StartLine) + Assert.Equal(startCol, lbrace.StartColumn) + Assert.Equal(startCol + expectedSpanLen, lbrace.EndColumn) + // right brace span: single line, starts at the end marker, expectedSpanLen columns wide + Assert.Equal(rbrace.StartLine, rbrace.EndLine) + Assert.Equal(endRow + 1, rbrace.StartLine) + Assert.Equal(endCol, rbrace.StartColumn) + Assert.Equal(endCol + expectedSpanLen, rbrace.EndColumn) + + checkBraces "(1" ")//1" 1 + checkBraces "( " ") *" 1 + checkBraces "{" "}" 1 + checkBraces "[// list_start" "]//list_end" 1 + checkBraces "[|" "|]" 2 + checkBraces "<@(* S0 *)" "@>(* E0 *)" 2 + checkBraces "<@(* S1 *)" "@>(* E1 *)" 2 + checkBraces "['x'" "](* E_L*)" 1 + checkBraces "[<" ">]" 2 diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs new file mode 100644 index 00000000000..96fc44ab2a5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs @@ -0,0 +1,64 @@ +module FSharp.Compiler.Service.Tests.TooltipActivePatternsTests + +open Xunit + +let private lazyActivePatternSource = + """let (|Lazy|) x = x + match 0 with | Lazy y -> ()""" + +[] +let ``ActivePatterns.Declaration`` () = + assertTooltipContains "int -> Choice" (markAtEndOfMarker "let ( |One|Two| ) x = One(x+1)" "ne|Tw") + +[] +let ``ActivePatterns.Result`` () = + assertTooltipContains "active pattern result One: int -> Choice" (markAtEndOfMarker "let ( |One|Two| ) x = One(x+1)" "= On") + +[] +let ``ActivePatterns.Value`` () = + let source = + """let ( |One|Two| ) x = One(x+1) + let patval = (|One|Two|) // use""" + + assertTooltipContains "int -> Choice" (markAtEndOfMarker source "= (|On") + +[] +let ``Regression.ActivePatterns.Bug4100a`` () = + assertTooltipDoesNotContain "'?" (markAtEndOfMarker lazyActivePatternSource "with | Laz") + assertTooltipContains "Lazy" (markAtEndOfMarker lazyActivePatternSource "with | Laz") + +[] +let ``Regression.ActivePatterns.Bug4100b`` () = + let source = + """let Some (a:int) = a +match None with +| Some _ -> () +| _ -> () + +let (|NSome|) (a:int) = a +let NSome (a:int) = a.ToString() +match 0 with +| NSome _ -> ()""" + + assertTooltipDoesNotContain "int -> int" (markAtEndOfMarker source "| Som") + assertTooltipContains "Option.Some" (markAtEndOfMarker source "| Som") + assertTooltipDoesNotContain "int -> string" (markAtEndOfMarker source "| NSom") + assertTooltipContains "active recognizer NSome" (markAtEndOfMarker source "| NSom") + +[] +let ``Regression.ActivePatterns.Bug4103`` () = + let marked = markAtEndOfMarker lazyActivePatternSource "(|Laz" + assertTooltipDoesNotContain "Control.Lazy" marked + assertTooltipContains "|Lazy|" marked + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_5`` () = + assertCompletionItemTooltipContainsInOrder + "Pattern" + [ "active recognizer Pattern: int"; "Pattern comment" ] + """module Module = + /// Pattern comment + let (|Pattern|) = 0 + +let x() = + Module.{caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs new file mode 100644 index 00000000000..bc8ff79b950 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs @@ -0,0 +1,74 @@ +module FSharp.Compiler.Service.Tests.TooltipAttributesTests + +open System +open Xunit + +[] +let ``EnsureNoAssertFromBadParserRangeOnAttribute`` () = + let source = + """ + [] + Types foo = int""" + + Checker.getTooltip (markAtEndOfMarker source "ype") |> ignore + +[] +[] a:")>] +[] a:")>] +let ``ParamsArrayArgument`` (marker: string) (expected: string) = + let source = + """ + type A() = + static member Foo([] a : int[]) = () + let r = A.Foo(42)""" + + assertTooltipContains expected (markAtEndOfMarker source marker) + +[] +let ``IdentifiersInAttributes`` () = + let source = + String.concat + "\n" + [ "[<(*test13*)System.CLSCompliant(true)>]" + "let test13 = 1" + "open System" + "[<(*test14*)CLSCompliant(true)>]" + "let test14 = 1" ] + + walk source "[<(*test13*)" "System" "namespace System" + walk source "[<(*test13*)System." "CLSCompliant" "CLSCompliantAttribute" + walk source "[<(*test14*)" "CLSCompliant" "CLSCompliantAttribute" + +[] +let ``Regression.FieldRepeatedInToolTip.Bug3818`` () = + let source = + """ + [] + type A() = + do ()""" + + assertIdentifierInTooltipExactlyOnce "Inherited" (markAtEndOfMarker source "Inherite") + +[] +let ``Automation.OverRiddenMembers`` () = + let source = + """namespace QuickinfoGeneric + + module FSharpOwnCode = + [] + type TextOutputSink() = + abstract WriteChar : char -> unit + abstract WriteString : string -> unit + default x.WriteString(s) = s |> String.iter x.WriteChar + + type ByteOutputSink() = + inherit TextOutputSink() + default sink.WriteChar(c) = System.Console.Write(c) + override sink.WriteString(s) = System.Console.Write(s) + + let sink = new ByteOutputSink() + sink.WriteChar(*Marker11*)('c') + sink.WriteString(*Marker12*)("Hello World!")""" + + assertTooltipContainsInFsFile "override ByteOutputSink.WriteChar: c: char -> unit" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "override ByteOutputSink.WriteString: s: string -> unit" (markAtStartOfMarker source "(*Marker12*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs new file mode 100644 index 00000000000..5cbb2c5bd3f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs @@ -0,0 +1,234 @@ +module FSharp.Compiler.Service.Tests.TooltipClassesTests + +open System +open System.IO +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.IO +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open TestFramework + +let private assertCrossFileTooltipContains + (expected: string) + (file1Name: string) + (file1Source: string) + (file2RelativePath: string) + (markedFile2: string) + = + let context = Checker.getResolveContext markedFile2 + let root = createTemporaryDirectory () + let projDir = Path.Combine(root.FullName, "proj") + Directory.CreateDirectory(projDir) |> ignore + let file1Path = Path.Combine(projDir, file1Name) + let file2LogicalPath = Path.Combine(projDir, file2RelativePath) + let file2PhysicalPath = Path.GetFullPath file2LogicalPath + Directory.CreateDirectory(Path.GetDirectoryName file2PhysicalPath) |> ignore + FileSystem.OpenFileForWriteShim(file1Path).Write(file1Source) + FileSystem.OpenFileForWriteShim(file2PhysicalPath).Write(context.Source) + + let dllName = Path.Combine(projDir, "CrossFile.dll") + let projName = Path.Combine(projDir, "CrossFile.fsproj") + let args = mkProjectCommandLineArgs(dllName, []) + + let options = + { checker.GetProjectOptionsFromCommandLineArgs(projName, args) with + SourceFiles = [| file1Path; file2LogicalPath |] } + + let _, checkResults = parseAndCheckFile file2LogicalPath context.Source options + + checkResults.GetTooltip(context) + |> foldToolTip + |> assertFoldedTooltipContains true "cross-file tooltip" expected + +let private assertProjectTooltipContains (projectName: string) (expected: string) (markedSource: string) = + foldedProjectTooltip [] [] markedSource + |> assertFoldedTooltipContains true (sprintf "tooltip in project %A" projectName) expected + +[] +let ``QuickInfo.LetBindingsInTypes`` () = + assertTooltipContains + "val fff: n: int -> int" + """type A() = + let ff{caret}f n = n + 1""" + +[] +let ``Basic`` () = + assertTooltipContains + "Bob =" + """type (*bob*)Bob{caret}() = + let x = 1""" + +[] +let ``TauStarter`` () = + assertTooltipContains + "Bob =" + """type (*Scenario01*)Bob() = + let x = 1 +type (*Scenario021*)Bob{caret} = + class + public new() = { } +end +type (*Scenario022*)Alice = + class + public new() = { } +end""" + + assertTooltipContains + "Alice =" + """type (*Scenario01*)Bob() = + let x = 1 +type (*Scenario021*)Bob = + class + public new() = { } +end +type (*Scenario022*)Alice{caret} = + class + public new() = { } +end""" + +[] +let ``MemberIdentifiers`` () = + let source = + String.concat + "\n" + [ "type TestType() =" + " member (*test6*) xx.PPPP = 1" + " member (*test7*) xx.QQQQ(x) = 3.0" + "let test8 = (TestType()).PPPP" ] + + let walk = EditorServiceAsserts.walk source + walk "member (*test6*) " "xx" "TestType" + walk "member (*test6*) xx." "PPPP" "PPPP" + walk "member (*test7*) " "xx" "TestType" + walk "member (*test7*) xx." "QQQQ" "float" + walk "let test8 = (TestType())." "PPPP" "PPPP" + +[] +let ``Regression.StaticVsInstance.Bug3626`` () = + let staticCall = + """type Foo() = + member this.Bar () = "hllo" + static member Bar() = 13 +let z = (*int*) Foo.Ba{caret}r() +let Hoo = new Foo() +let y = (*string*) Hoo.Bar()""" + + assertTooltipContains "Foo.Bar" staticCall + assertTooltipContains "-> int" staticCall + + let instanceCall = + """type Foo() = + member this.Bar () = "hllo" + static member Bar() = 13 +let z = (*int*) Foo.Bar() +let Hoo = new Foo() +let y = (*string*) Hoo.Ba{caret}r()""" + + assertTooltipContains "Foo.Bar" instanceCall + assertTooltipContains "-> string" instanceCall + +[] +let ``Regression.Classes.Bug4066`` () = + let source = "type Foo() as this =\n do this |> ignore\n member this.Bar() = this" + + for marker in [ "as thi"; "do thi"; "member thi"; "Bar() = thi" ] do + let marked = markAtEndOfMarker source marker + assertTooltipContains "val this: Foo" marked + assertTooltipDoesNotContain "ref" marked + +[] +let ``AcrossTwoProjects`` () = + assertProjectTooltipContains + "testproject1" + "Bob1 =" + """type (*bob*)Bob{caret}1() = + let x = 1""" + + assertProjectTooltipContains + "testproject2" + "Bob2 =" + """type (*bob*)Bob{caret}2() = + let x = 1""" + +[] +[] +[] +let ``AcrossMultipleFiles`` (file2RelativePath: string) = + assertCrossFileTooltipContains + "File1.Bob" + "File1.fs" + "type Bob() =\n let x = 1\n" + file2RelativePath + "let bo{caret}b = new File1.Bob()" + +[] +let ``AcrossLinkedFiles`` () = + assertCrossFileTooltipContains + "Link.Bob" + "link.fs" + "type Bob() =\n let x = 1\n" + "File2.fs" + "let bo{caret}b = new Link.Bob()" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_9`` () = + assertTooltipContainsInOrder + [ "type Class"; "A comment" ] + """module Module = + /// A comment + type Class = class end +let _ = typeof""" + +[] +let ``Regression.Class.Printing.CSharp.Classes.Only.Bug4592`` () = + assertTooltipContainsInOrder + [ "type Random =" + " new: unit -> unit + 1 overload" + " member Next: unit -> int + 2 overloads" + " member NextBytes: buffer: byte array -> unit" + " member NextDouble: unit -> float" ] + "let _ = typeof" + +#if !NETCOREAPP +let private getWinFormsTooltip (markedSource: string) = + getTooltipWithReferences + "WinFormsTooltip" + [ fsCoreDefaultReference () + sysLib "mscorlib" + sysLib "System" + sysLib "System.Core" + sysLib "System.Drawing" + sysLib "System.Windows.Forms" ] + markedSource + +[] +let ``Regression.CompListItemInfo.Bug5694`` () = + let actual = + getWinFormsTooltip + """type Form2() as self = + inherit System.Windows.Forms.Form() + member _.M() = self.AcceptB{caret}utton""" + |> foldToolTip + + let expected = + "Gets or sets the button on the form that is clicked when the user presses the ENTER key." + + if not (actual.Contains expected) then + failwithf "Expected tooltip to contain %A, but the actual tooltip was:\n%s" expected actual + +[] +let ``Regression.Class.Printing.CSharp.Classes.Bug4624`` () = + assertTooltipContainsInOrder + [ "type CodeConnectAccess =" + " new: allowScheme: string * allowPort: int -> unit" + " member Equals: o: obj -> bool" + " member GetHashCode: unit -> int" + " static member CreateAnySchemeAccess: allowPort: int -> CodeConnectAccess" + " static member CreateOriginSchemeAccess: allowPort: int -> CodeConnectAccess" + " static val AnyScheme: string" + " static val DefaultPort: int" + " ..." ] + "let _ = typeof" +#endif diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs new file mode 100644 index 00000000000..e0a79700f46 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs @@ -0,0 +1,228 @@ +module FSharp.Compiler.Service.Tests.TooltipComputationExpressionsTests + +open Xunit + +let private identifierHaveDiffMeaningsSource = """namespace NS + module float(*Marker1_1*) = + + let GenerateTuple = fun x -> let tuple = (x,x.ToString(),(float(*Marker1_2*))x, ( fun y -> (y.ToString(),y+1)) ) + tuple + + let MySeq : seq(*Marker2_1*) = + seq(*Marker2_2*) { + + for i in 1..9 do + + let myTuple = GenerateTuple i + let fieldInt,fieldString,fieldFloat,_ = myTuple + yield fieldFloat + } + + let MySet : Set(*Marker3_1*) = + MySeq + |> Array.ofSeq + |> List.ofArray + |> Set(*Marker3_2*).ofList + + let int(*Marker4_1*) : int(*Marker4_2*) = 1 + + type int(*Marker4_3*)() = + member this.M = 1 + + type T(*Marker5_1*)() = + [] + val mutable T : T + + let T = new T() + let t = T.T.T.T(*Marker5_2*); + + type ValType() = + member this.Value with get(*Marker6_1*) () = 10 + and set(*Marker6_2*) x = x + 1 |> ignore""" + +let private typeAbbreviationsSource = """namespace NS + module TypeAbbreviation = + + type MyInt(*Marker1_1*) = int + + type PairOfFloat(*Marker2_1*) = float * float + + + type AbAttrName(*Marker5_1*) = AbstractClassAttribute + + + type IA(*Marker3_1*) = + abstract AbstractMember : int -> int + + [] + type ClassIA(*Marker3_2*)() = + interface IA with + member this.AbstractMember x = x + 1 + + type GenericClass(*Marker4_1*)<'a when 'a :> IA>() = + static member StaticMember(x:'a) = x.AbstractMember(1) + + + let GenerateTuple = fun ( x : MyInt) -> + let myInt(*Marker1_2*),float1,float2,function1 = (x,(float)x,(float)x, ( fun y -> (y.ToString(),y+1)) ) + myInt,((float1,float2):PairOfFloat),function1 + + let MySeq(*Marker2_2*) = + seq { + + for i in 1..9 do + let myInt,pairofFloat,function1 = GenerateTuple i + + yield pairofFloat + } + + let genericClass(*Marker4_2*) = new GenericClass()""" + +let private whereQuickInfoShouldNotShowUpSource = """namespace Test + + module Helper = + /// Tests if passed System.Numerics.BigInteger(*Marker1*) argument is prime + let IsPrime x = + let mutable i = 2I + let mutable foundFactor = false + while not foundFactor && i < x do + (* + the most naive way to test for number being prime + Works great for small int(*Marker2*) + *) + if x % i = 0I then + foundFactor <- true + i <- i + 1I + not foundFactor + + module App = + open Helper + + let sumOfAllPrimesUnder1Mi = + #if TEST_TWO_MI + seq(*Marker4*) { 1I .. 2000000I } + #else + seq { 1I .. 1000000I(*Marker7*) } + #endif + |> Seq.filter(IsPrime) + // find result after filtering seq(*Marker3*) + |> Seq.sum + + let myString hello = "hello"(*Marker5*) + + myString "myString"(*Marker8*) + |> Seq.filter (fun c -> int c > 75) + |> Seq.item 0 + |> (=) 'e'(*Marker6*) + |> ignore""" + +let private xDelegateSource = """module Test + + open FSTestLib + + open System.Runtime.InteropServices + let ctrlSignal = ref false + [] + extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) + let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) + let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) + + let IsInstanceMethod (controlEventHandler:ControlEventHandler) = + // TC 32 Identifier Delegate Own Code Pattern Match + match controlEventHandler(*Marker1*).Method.IsStatic with + | true -> printf "It's not a instance method. " + | false -> printf " It's a instance method. " + + // TC 33 Event DiscUnion Own Code Quotation + let a = <@ MyDistance.Event(*Marker2*) @> + + let DelegateSeq = + seq { for i in 1..10 do + let newDelegate = new ControlEventHandler(MyCar.Run) + // TC 35 Identifier Delegate Own Code Comp Expression + yield newDelegate(*Marker3*) } + + let StructFieldSeq = + seq { for i in 1..10 do + let a = MyPoint((float)i,2.0) + // TC 36 Field Struct Own Code Comp Expression + yield a.X(*Marker4*) }""" + +let private asyncToolTipsSource = """let a = + async { + let ms = new System.IO.MemoryStream(Array.create 1000 1uy) + let toFill = Array.create 2000 0uy + let! x = ms.AsyncRead(2000) + return x + }""" + +[] +let ``Automation.IdentifierHaveDiffMeanings`` () = + let source = identifierHaveDiffMeaningsSource + assertTooltipContainsInFsFile "module float" (markAtStartOfMarker source "(*Marker1_1*)") + assertTooltipContainsInFsFile "val float: 'T -> float (requires member op_Explicit)" (markAtStartOfMarker source "(*Marker1_2*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.Operators.float" (markAtStartOfMarker source "(*Marker1_2*)") + assertTooltipContainsInFsFile "type float = System.Double" (markAtStartOfMarker source "(*Marker1_3*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.float" (markAtStartOfMarker source "(*Marker1_3*)") + assertTooltipContainsInFsFile "type seq<'T> = System.Collections.Generic.IEnumerable<'T>" (markAtStartOfMarker source "(*Marker2_1*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Collections.seq<_>" (markAtStartOfMarker source "(*Marker2_1*)") + assertTooltipContainsInFsFile "val seq: 'T seq -> 'T seq" (markAtStartOfMarker source "(*Marker2_2*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.Operators.seq" (markAtStartOfMarker source "(*Marker2_2*)") + assertTooltipContainsInFsFile "type Set<'T (requires comparison)> =" (markAtStartOfMarker source "(*Marker3_1*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Collections.Set" (markAtStartOfMarker source "(*Marker3_1*)") + assertTooltipContainsInFsFile "module Set" (markAtStartOfMarker source "(*Marker3_2*)") + assertTooltipContainsInFsFile "Functional programming operators related to the Set<_> type" (markAtStartOfMarker source "(*Marker3_2*)") + assertTooltipContainsInFsFile "val int: int" (markAtStartOfMarker source "(*Marker4_1*)") + assertTooltipContainsInFsFile "Full name: NS.float.int" (markAtStartOfMarker source "(*Marker4_1*)") + assertTooltipContainsInFsFile "type int = int32" (markAtStartOfMarker source "(*Marker4_2*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.int" (markAtStartOfMarker source "(*Marker4_2*)") + assertTooltipContainsInFsFile "type int =" (markAtStartOfMarker source "(*Marker4_3*)") + assertTooltipContainsInFsFile "member M: int" (markAtStartOfMarker source "(*Marker4_3*)") + assertTooltipContainsInFsFile "type T =" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "new : unit -> T" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "val mutable T: T" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "T.T: T" (markAtStartOfMarker source "(*Marker5_2*)") + assertTooltipContainsInFsFile "member ValType.Value : int" (markAtStartOfMarker source "(*Marker6_1*)") + assertTooltipContainsInFsFile "member ValType.Value : int with set" (markAtStartOfMarker source "(*Marker6_2*)") + assertTooltipDoesNotContainInFsFile "Microsoft.FSharp.Core.ExtraTopLevelOperators.set" (markAtStartOfMarker source "(*Marker6_2*)") + +[] +let ``Automation.TypeAbbreviations`` () = + let source = typeAbbreviationsSource + assertTooltipContainsInFsFile "type MyInt = int" (markAtStartOfMarker source "(*Marker1_1*)") + assertTooltipContainsInFsFile "val myInt: MyInt" (markAtStartOfMarker source "(*Marker1_2*)") + assertTooltipContainsInFsFile "type PairOfFloat = float * float" (markAtStartOfMarker source "(*Marker2_1*)") + assertTooltipContainsInFsFile "val MySeq: PairOfFloat seq" (markAtStartOfMarker source "(*Marker2_2*)") + assertTooltipContainsInFsFile "type IA =" (markAtStartOfMarker source "(*Marker3_1*)") + assertTooltipContainsInFsFile "type ClassIA =" (markAtStartOfMarker source "(*Marker3_2*)") + assertTooltipContainsInFsFile "type GenericClass<'a (requires 'a :> IA)> =" (markAtStartOfMarker source "(*Marker4_1*)") + assertTooltipContainsInFsFile "val genericClass: GenericClass" (markAtStartOfMarker source "(*Marker4_2*)") + assertTooltipContainsInFsFile "type AbAttrName = AbstractClassAttribute" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "type AbAttrName = AbstractClassAttribute" (markAtStartOfMarker source "(*Marker5_2*)") + +[] +let ``Automation.WhereQuickInfoShouldNotShowUp`` () = + let source = whereQuickInfoShouldNotShowUpSource + assertTooltipDoesNotContainInFsFile "BigInteger" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipDoesNotContainInFsFile "int" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipDoesNotContainInFsFile "seq" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipDoesNotContainInFsFile "seq" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipDoesNotContainInFsFile "hello" (markAtStartOfMarker source "(*Marker5*)") + assertTooltipDoesNotContainInFsFile "char" (markAtStartOfMarker source "(*Marker6*)") + assertTooltipDoesNotContainInFsFile "bigint" (markAtStartOfMarker source "(*Marker7*)") + assertTooltipDoesNotContainInFsFile "myString" (markAtStartOfMarker source "(*Marker8*)") + +[] +let ``Automation.XDelegateDUStructfromOwnCode`` () = + let source = xDelegateSource + assertTooltipContainsWithFsTestLib "val controlEventHandler: ControlEventHandler" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsWithFsTestLib "property MyDistance.Event: Event" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContainsWithFsTestLib "val newDelegate: ControlEventHandler" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContainsWithFsTestLib "property MyPoint.X: float" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContainsWithFsTestLib "Gets and sets X" (markAtStartOfMarker source "(*Marker4*)") + +[] +let ``Async.AsyncToolTips`` () = + let source = asyncToolTipsSource + assertTooltipContains "AsyncBuilder" (markAtEndOfMarker source "asy") + assertTooltipDoesNotContain "---" (markAtEndOfMarker source "asy") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs new file mode 100644 index 00000000000..0f49ba8ead2 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs @@ -0,0 +1,166 @@ +module FSharp.Compiler.Service.Tests.TooltipDeclarationsTests + +open System +open Xunit +open FSharp.Test +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +[] +let ``Regression.ImportedEvent.138110`` () = + let source = + """ +open Microsoft.FSharp.Core.CompilerServices +let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate +""" + + assertTooltipContains "Invalidate" (markAtStartOfMarker source "Provider(*$$$*)") + +[] +let ``OrphanFs.BaselineIntellisenseStillWorks`` () = + assertTooltipContains "val astring: string" (markAtEndOfMarker """let astring = "Hello" """ "let astr") + +[] +let ``Global.LongPaths`` () = + let source = + String.concat + "\n" + [ "let test0 = global.System.Console.In" + "let test0b = global.System.Collections.Generic.List()" + "let test0c = global.System.Collections.Generic.KeyNotFoundException()" + "type Test0d = global.System.Collections.Generic.List" + "type Test0e = global.System.Collections.Generic.KeyNotFoundException" ] + + walk source "let test0 = global.System." "Console" "Console =" + walk source "let test0 = global.System.Console." "In" "System.Console.In" + walk source "let test0 = global.System.Console." "In" "TextReader" + walk source "let test0b = global.System." "Collections" "namespace System.Collections" + walk source "let test0b = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "let test0b = global.System.Collections.Generic." "List" "List()" + walk source "let test0c = global.System." "Collections" "namespace System.Collections" + walk source "let test0c = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "let test0c = global.System.Collections.Generic." "KeyNotFoundException" "KeyNotFoundException()" + walk source "type Test0d = global.System." "Collections" "namespace System.Collections" + walk source "type Test0d = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "type Test0d = global.System.Collections.Generic." "List" "Generic.List" + walk source "type Test0e = global.System." "Collections" "namespace System.Collections" + walk source "type Test0e = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "type Test0e = global.System.Collections.Generic." "KeyNotFoundException" "Generic.KeyNotFoundException" + +[] +let ``MethodAndPropTooltip`` () = + let source = + """ +open System +do + Console.Clear() + Console.BackgroundColor |> ignore""" + + assertIdentifierInTooltipExactlyOnce "Clear" (markAtEndOfMarker source "Console.Cle") + assertIdentifierInTooltipExactlyOnce "BackgroundColor" (markAtEndOfMarker source "Console.Back") + +[] +let ``Automation.Regression.AccessibilityOnTypeMembers.Bug4168`` () = + let source = + """module Test +type internal Foo2(*Marker*) () = + member public this.Prop1 = 12 + member internal this.Prop2 = 12 + member private this.Prop3 = 12 + public new(x: int) = new Foo2() + internal new(x: int, y: int) = new Foo2() + private new(x: int, y: int, z: int) = new Foo2()""" + + assertTooltipContains "type internal Foo2" (markAtStartOfMarker source "(*Marker*)") + +[] +let ``Automation.AutoOpenMyNamespace`` () = + let source = + """namespace System.Numerics +type t = BigInteger(*Marker1*)""" + + assertTooltipContainsInFsFile "type BigInteger" (markAtStartOfMarker source "r(*Marker1*)") + +[] +let ``Automation.Regression.TupleException.Bug3723`` () = + let source = + """namespace TestQuickinfo +exception E3(*Marker1*) of int * int +exception E4(*Marker2*) of (int * int) +exception E5(*Marker3*) = E4""" + + assertTooltipContainsInFsFile "exception E3 of int * int" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.E3" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsInFsFile "exception E4 of (int * int)" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.E4" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContainsInFsFile "exception E5 = E4" (markAtStartOfMarker source "(*Marker3*)") + +[] +let ``Automation.Regression.XmlDocComments.Bug3157`` () = + let source = + """namespace TestQuickinfo +module XmlComment = + /// XmlComment J + let func(*Marker*) x = + /// XmlComment K + let rec g x = 1 + g x""" + + let marked = markAtStartOfMarker source "(*Marker*)" + assertTooltipContainsInFsFile "val func: x: 'a -> int" marked + assertTooltipContainsInFsFile "XmlComment J" marked + assertTooltipContainsInFsFile "Full name: TestQuickinfo.XmlComment.func" marked + assertTooltipDoesNotContainInFsFile "XmlComment K" marked + +let private referenceTooltipAtCaret (markedSource: string) = + let context = SourceContext.fromMarkedSource markedSource + let _, checkResults = getParseAndCheckResultsUniqueName context.Source + checkResults.GetToolTip(context.CaretPos.Line, context.CaretPos.Column, context.LineText, ([]: string list), FSharpTokenTag.String) + |> foldToolTip + +let private assertReferenceTooltipContains (expected: string) (markedSource: string) = + referenceTooltipAtCaret markedSource + |> assertFoldedTooltipContains true "#r reference tooltip" expected + +let private assertReferenceTooltipDoesNotContain (notExpected: string) (markedSource: string) = + referenceTooltipAtCaret markedSource + |> assertFoldedTooltipContains false "#r reference tooltip" notExpected + +[] +let ``Fsx.Bug4311HoverOverReferenceInFirstLine`` () = + let source = "#r \"PresentationFramework.dll\"\n\n#r \"PresentationCore.dll\" " + assertReferenceTooltipContains "PresentationFramework.dll" (markAtEndOfMarker source "#r \"PresentationFrame") + assertReferenceTooltipDoesNotContain "multiple results" (markAtEndOfMarker source "#r \"PresentationFrame") + +[] +let ``Fsx.Bug5073`` () = + let source = "#r \"System\" " + assertReferenceTooltipContains @"Reference Assemblies\Microsoft" (markAtEndOfMarker source "#r \"Sys") + assertReferenceTooltipContains ".NETFramework" (markAtEndOfMarker source "#r \"Sys") + +[] +let ``Fsx.HashR_QuickInfo.BugDefaultReferenceFileIsAlsoResolved`` () = + assertReferenceTooltipContains "System.dll" (markAtEndOfMarker "#r \"System\" " "#r \"Syst") + +[] +let ``Fsx.HashR_QuickInfo.DoubleReference`` () = + let source = "#r \"System\" // Mark1\n#r \"System\" // Mark2 " + assertReferenceTooltipContains "System.dll" (markAtStartOfMarker source "tem\" // Mark1") + assertReferenceTooltipContains "System.dll" (markAtStartOfMarker source "tem\" // Mark2") + +[] +let ``Fsx.HashR_QuickInfo.ResolveFromGAC`` () = + let marked = markAtEndOfMarker "#r \"CustomMarshalers\" " "#r \"Custo" + assertReferenceTooltipContains ".NETFramework" marked + assertReferenceTooltipContains "CustomMarshalers.dll" marked + +[] +let ``Fsx.HashR_QuickInfo.ResolveFromFullyQualifiedPath`` () = + let path = System.IO.Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll") + let source = sprintf "#r @\"%s\"" path + let marker = "#r @\"" + path.Substring(0, path.Length / 2) + let marked = markAtEndOfMarker source marker + assertReferenceTooltipContains path marked + assertReferenceTooltipContains (System.Reflection.AssemblyName.GetAssemblyName(path).ToString()) marked diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..b2a616d5b02 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs @@ -0,0 +1,171 @@ +module FSharp.Compiler.Service.Tests.TooltipDiscriminatedUnionsTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open TestFramework + +let private assertTooltipContainsWithProvider (expected: string) (markedSource: string) = + Checker.getTooltipWithOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + markedSource + |> foldToolTip + |> assertFoldedTooltipContains true "provider tooltip" expected + +let private priorityQueueSource = + """open System +type PriorityQueue(*MarkerType*)<'k,'a> = + | Nil(*MarkerDataConstructor*) + | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a> +module PriorityQueue(*MarkerModule*) = + let empty = Nil + let minKeyValue = function + | Nil -> failwith "empty queue" + | Branch(k,a,_,_) -> (k,a) + let minKey pq = fst (minKeyValue pq(*MarkerVal*)) + let singleton(*MarkerLastLine*) k a = Branch(k,a,Nil,Nil)""" + +[] +let ``TypeConstructorQuickInfo`` () = + assertTooltipContainsInOrder + [ "type PriorityQueue<'k,'a> =" + "| Nil" + "| Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a>" ] + (markAtStartOfMarker priorityQueueSource "(*MarkerType*)") + + assertTooltipContains + "union case PriorityQueue.Nil: PriorityQueue<'k,'a>" + (markAtStartOfMarker priorityQueueSource "(*MarkerDataConstructor*)") + + assertTooltipContainsInOrder + [ "module PriorityQueue"; "from Test" ] + (markAtStartOfMarker priorityQueueSource "(*MarkerModule*)") + + assertTooltipContains "val pq: PriorityQueue<'a,'b>" (markAtStartOfMarker priorityQueueSource "(*MarkerVal*)") + + assertTooltipContains + "val singleton: k: 'a -> a: 'b -> PriorityQueue<'a,'b>" + (markAtStartOfMarker priorityQueueSource "(*MarkerLastLine*)") + +[] +let ``NamedDUFieldQuickInfo`` () = + let source = + """type NamedFieldDU(*MarkerType*) = + | Case1(*MarkerCase1*) of V1 : int * bool * V3 : float + | Case2(*MarkerCase2*) of ``Big Name`` : int * Item2 : bool + | Case3(*MarkerCase3*) of Item : int +exception NamedExn(*MarkerException*) of int * V2 : string * bool * Data9 : float""" + + assertTooltipContainsInOrder + [ "type NamedFieldDU =" + "| Case1 of V1: int * bool * V3: float" + "| Case2 of ``Big Name`` : int * bool" + "| Case3 of int" ] + (markAtStartOfMarker source "(*MarkerType*)") + + assertTooltipContains + "union case NamedFieldDU.Case1: V1: int * bool * V3: float -> NamedFieldDU" + (markAtStartOfMarker source "(*MarkerCase1*)") + + assertTooltipContains + "union case NamedFieldDU.Case2: ``Big Name`` : int * bool -> NamedFieldDU" + (markAtStartOfMarker source "(*MarkerCase2*)") + + assertTooltipContains "union case NamedFieldDU.Case3: int -> NamedFieldDU" (markAtStartOfMarker source "(*MarkerCase3*)") + + assertTooltipContains + "exception NamedExn of int * V2: string * bool * Data9: float" + (markAtStartOfMarker source "(*MarkerException*)") + +[] +let ``Regression.InDeclaration.Bug3176d`` () = + let source = + """type DU<'a> = + | DULabel of 'a""" + + assertTooltipContains "DULabel: 'a -> DU<'a>" (markAtEndOfMarker source "DULab") + +[] +let ``IdentifiersForUnionCases`` () = + let source = + String.concat "\n" [ "type TestType10 = Case1 | Case2 of int"; "let test12 = (Case1,Case2(3))" ] + + walk source "type TestType10 = " "Case1" "union case TestType10.Case1" + walk source "type TestType10 = Case1 | " "Case2" "union case TestType10.Case2" + walk source "let test12 = (" "Case1" "union case TestType10.Case1" + walk source "let test12 = (Case1," "Case2" "union case TestType10.Case2" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_3`` () = + assertTooltipContainsInOrder + [ "union case Module.Union.Case: int -> Module.Union"; "Case comment" ] + """module Module = + /// Union comment + type Union = + /// Case comment + | Case of int + +let x() = Module.Ca{caret}se""" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_4`` () = + assertTooltipContainsInOrder + [ "type Union ="; "| Case of int"; "Union comment" ] + """module Module = + /// Union comment + type Union = + /// Case comment + | Case of int + +let _ = typeof""" + +[] +let ``XmlDocCommentsForArguments`` () = + let source = + """type bar() = + /// Test for members + /// x1 param! + member this.foo + (x1:int)= + System.Console.WriteLine(x1.ToString()) +type Uni1 = + /// Test for unions + /// str of case1 + | Case1 of str: string + | None +/// Test for exception types +/// value param +exception Ex1 of value: string +// Methods +let f1 = (new bar()).foo(*Marker0*)(x1(*Marker1*) = 10) +let f2 = System.String.Concat(1, arg1(*Marker2*) = "") +//Unions +let f3 = Case1(str(*Marker3*) = "10") +match f3 with +| Case1(str(*Marker4*) = "10") -> () +| _ -> () +//Exceptions +let f4 = Ex1(value(*Marker5*) = "") +try + () +with + Ex1(value(*Marker6*) = v) -> () +//Static parameters of type providers +type provType = N1.T""" + + assertTooltipContains "Test for members" (markAtStartOfMarker source "(*Marker0*)") + assertTooltipContains "x1 param!" (markAtStartOfMarker source "(*Marker1*)") + + assertTooltipContains + "Concatenates the string representations of two specified objects." + (markAtStartOfMarker source "(*Marker2*)") + + assertTooltipContains "str of case1" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContains "str of case1" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContains "value param" (markAtStartOfMarker source "(*Marker5*)") + assertTooltipContains "value param" (markAtStartOfMarker source "(*Marker6*)") + assertTooltipContainsWithProvider "Param1 of string" (markAtStartOfMarker source "(*Marker7*)") + assertTooltipContainsWithProvider "Ignored" (markAtStartOfMarker source "(*Marker8*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs new file mode 100644 index 00000000000..22bb8d65f95 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs @@ -0,0 +1,237 @@ +module FSharp.Compiler.Service.Tests.TooltipExpressionsTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +let private assertOperatorTooltipContains (expected: string) (operatorName: string) (markedSource: string) = + let context = SourceContext.fromMarkedSource markedSource + let _, checkResults = getParseAndCheckResults context.Source + + checkResults.GetToolTip(context.CaretPos.Line, context.CaretPos.Column + 1, context.LineText, [ operatorName ], FSharpTokenTag.Identifier) + |> foldToolTip + |> assertFoldedTooltipContains true "operator tooltip" expected + +[] +let ``Operators.TopLevel`` () = + assertOperatorTooltipContains + "tooltip for operator" + "===" + "/// tooltip for operator\nlet (===) a b = a + b\nlet _ = \"\" ==={caret} \"\"" + +[] +let ``Operators.Member`` () = + assertOperatorTooltipContains + "tooltip for operator" + "+++" + "type U = U\n with\n /// tooltip for operator\n static member (+++) (U, U) = U\nlet _ = U +++{caret} U" + +[] +let ``QuickInfoForQuotedIdentifiers`` () = + let source = + "/// The fff function\nlet fff x = x\n/// The gg gg function\nlet ``gg gg`` x = x\nlet r = fff 1 + ``gg gg`` 2 // no tip hovering over" + + let identifier = "``gg gg``" + + for i in 1 .. identifier.Length - 1 do + let marker = "+ " + identifier.Substring(0, i) + assertTooltipContains "gg gg" (markAtEndOfMarker source marker) + +[] +let ``QuickInfoSingleCharQuotedIdentifier`` () = + assertTooltipContains "val x: int" "let ``x`` = 10\n``x{caret}``|> printfn \"%A\"" + +[] +let ``IntArrayQuickInfo`` () = + let source = + "let x(*MIntArray1*) : int array = [| 1; 2; 3 |]\nlet y(*MInt[]*) : int [] = [| 1; 2; 3 |]" + + assertTooltipContains "int array" (markAtStartOfMarker source "(*MIntArray1*)") + assertTooltipContains "int array" (markAtStartOfMarker source "(*MInt[]*)") + +[] +let ``LinkNameStringQuickInfo`` () = + assertTooltipDoesNotContain "val" "let y = 1\nlet f x = \"{caret}x\"(*Marker1*)\nlet g z = \"y\"(*Marker2*)" + assertTooltipDoesNotContain "val" "let y = 1\nlet f x = \"x\"(*Marker1*)\nlet g z = \"{caret}y\"(*Marker2*)" + assertTooltipContains "val y: int" "let y{caret} = 1\nlet f x = \"x\"(*Marker1*)\nlet g z = \"y\"(*Marker2*)" + +[] +let ``IdentifierWithTick`` () = + let source = "let x = 1\nlet x' = \"foo\"\nif (*aaa*)x = 1 then (*bbb*)x' else \"\"" + assertTooltipContains "val x: int" (markAtEndOfMarker source "(*aaa*)x") + assertTooltipContains "val x': string" (markAtEndOfMarker source "(*bbb*)x'") + +[] +let ``NegativeTest.CharLiteralNotConfusedWithIdentifierWithTick`` () = + assertTooltipDoesNotContain "val x" (markAtEndOfMarker "let x = 1\nlet y = 'x'" "'x") + assertTooltipContains "val x: int" "let x{caret} = 1\nlet y = 'x'" + +[] +let ``StringLiteralWithIdentifierLookALikes.Bug2360_A`` () = + let source = "let y = 1\nlet f x = \"x\"\nlet g z = \"y\"" + assertTooltipDoesNotContain "val" (markAtEndOfMarker source "f x = \"") + assertTooltipContains "val y: int" (markAtEndOfMarker source "let y") + +[] +let ``Regression.StringLiteralWithIdentifierLookALikes.Bug2360_B`` () = + assertTooltipContains "val y: int" (markAtEndOfMarker "let y = 1" "let y") + +[] +let ``Class.OnlyClassInfo`` () = + let source = "type TT(x : int, ?y : int) =\n class end" + let marked = markAtEndOfMarker source "type T" + assertTooltipContains "type TT" marked + assertTooltipDoesNotContain "---" marked + +[] +let ``Regression.Classes.Bug2362`` () = + let source = "let append mm nn = fun ac -> mm (nn ac)" + assertTooltipContains "mm: ('a -> 'b) -> nn: ('c -> 'a) -> ac: 'c -> 'b" (markAtEndOfMarker source "let appen") + assertTooltipContains "'a -> 'b" (markAtEndOfMarker source "let append m") + assertTooltipContains "'c -> 'a" (markAtEndOfMarker source "let append mm n") + +[] +let ``Regression.NoTooltipForOperators.Bug4567`` () = + assertOperatorTooltipContains + "val (|+|) : a: int -> b: int -> int" + "|+|" + "let ( |+|{caret} ) a b = a + b\nlet n = 1 |+| 2\nlet b = true || false\n()" + + assertOperatorTooltipContains + "val (|+|) : a: int -> b: int -> int" + "|+|" + "let ( |+| ) a b = a + b\nlet n = 1 |+|{caret} 2\nlet b = true || false\n()" + + assertOperatorTooltipContains + "val (||) : e1: bool -> e2: bool -> bool" + "||" + "let ( |+| ) a b = a + b\nlet n = 1 |+| 2\nlet b = true ||{caret} false\n()" + +[] +let ``Regression.Bug1605`` () = + assertTooltipContains + "val string: value: 'T -> string" + (markAtEndOfMarker "let rec f l =\n match l with\n | [] -> string.Format(\n | x::xs -> \"hello\"" "| [] -> str") + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_6`` () = + let source = + "module Module =\n /// A comment\n exception MyException of int\nlet x() =\n Module.MyExcep{caret}tion |> ignore" + + assertTooltipContainsInOrder [ "exception MyException of int"; "A comment" ] source + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpEntity as ent -> + if ent.XmlDocSig <> "T:Test.Module.MyException" then + failwithf "Unexpected XmlDocSig for own-code MyException: %s" ent.XmlDocSig + + if ent.Assembly.FileName |> Option.isSome then + failwithf "Expected own-code MyException to have no backing assembly file, but got %A" ent.Assembly.FileName + | sym -> failwithf "Expected an entity symbol for MyException, but got %A" sym + +let private accessorsAndMutatorsSource = + """type TestType1(*Marker1*)( x : int , y : int ) = + let mutable x = x + let mutable y = y + member this.X with get () = x + and set x' = x <- x' + member this.Y with set y' = y <- y' + member this.Length with get () = sqrt(float (x * x + y * y)) + member this.Item with get (i : int) = match i with | 0 -> x | 1 -> y | _ -> failwith "Incorrect index" +let point = TestType1(10,10) +point.X <- 3 +point.Y <- 4 +let xx = point.[0] +let yy = point.[1] +let bitArray = new System.Collections.BitArray(*Marker2*)(1) +point.Length |> ignore""" + +[] +let ``Automation.Regression.AccessorsAndMutators.Bug4276`` () = + let m1 = markAtStartOfMarker accessorsAndMutatorsSource "(*Marker1*)" + assertTooltipContains "type TestType1" m1 + assertTooltipContains "member Length: float" m1 + assertTooltipContains "member Item" m1 + assertTooltipContains "member X: int" m1 + assertTooltipContains "member Y: int" m1 + + let m2 = markAtStartOfMarker accessorsAndMutatorsSource "(*Marker2*)" + assertTooltipContains "type BitArray" m2 + assertTooltipContains "member And: value: BitArray -> BitArray" m2 + assertTooltipDoesNotContain "get_Length" m2 + assertTooltipDoesNotContain "set_Length" m2 + +let private tupleRecordClassOwnCodeConsumerSource = + """module Test + +open FSTestLib + +let AbsTuple = + fun x -> + let tuple1 = (x, x.ToString(), (float) x, (fun y -> (y.ToString(), y + 1))) + let tuple2 = (-x, (-x).ToString(), (float) (-x), (fun y -> (y.ToString(), y + 1))) + if x >= 0 then tuple1(*Marker1*) + else tuple2 + +let GenerateMyEmployee name age = + let a = MyEmployee.MakeDummy() + a.Name <- name + a.Age <- age + a.IsFTE <- System.Convert.ToBoolean(System.Random().Next(2)) + match a.IsFTE with + | true -> a + | _ -> MyEmployee(*Marker2*).MakeDummy() + +let myCarQuot = <@ new MyCar(*Marker3*)(19, MyColors.Red) @> + +let MaxTuple x y = + let tuplex = (x, x.ToString()) + let tupley = (y, (y).ToString()) + match x > y with + | true -> tuplex(*Marker4*) + | false -> tupley""" + +[] +let ``Automation.TupleRecordClassfromOwnCode`` () = + assertTooltipContainsWithFsTestLib + "val tuple1: int * string * float * (int -> string * int)" + (markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker1*)") + + let m2 = markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker2*)" + assertTooltipContainsWithFsTestLib "type MyEmployee" m2 + assertTooltipContainsWithFsTestLib "Full name: FSTestLib.MyEmployee" m2 + + let m3 = markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker3*)" + assertTooltipContainsWithFsTestLib "type MyCar" m3 + assertTooltipContainsWithFsTestLib "Full name: FSTestLib.MyCar" m3 + + assertTooltipContainsWithFsTestLib + "val tuplex: 'a * string" + (markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker4*)") + +[] +let ``Fsx.QuickInfo.Bug4979`` () = + assertTooltipContains + "The left or right SHIFT modifier key." + "System.ConsoleModifiers.Sh{caret}ift |> ignore\n(3).ToString().Length |> ignore" + + let tolerantAssemblies = + set + [ "netstandard.dll" + "System.Runtime.dll" + "System.Private.CoreLib.dll" + "System.Console.dll" + "mscorlib.dll" ] + + match (Checker.getSymbolUse "System.ConsoleModifiers.Shift |> ignore\n(3).ToString().Len{caret}gth |> ignore").Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + if m.XmlDocSig <> "P:System.String.Length" then + failwithf "Unexpected XmlDocSig for String.Length: %s" m.XmlDocSig + + match m.Assembly.FileName |> Option.map System.IO.Path.GetFileName with + | Some basename when tolerantAssemblies.Contains basename -> () + | other -> failwithf "Expected String.Length to be defined in one of %A, but got %A" tolerantAssemblies other + | sym -> failwithf "Expected a member symbol for String.Length, but got %A" sym diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs new file mode 100644 index 00000000000..b78dd00985a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs @@ -0,0 +1,73 @@ +module FSharp.Compiler.Service.Tests.TooltipGenericsTests + +open System +open Xunit +open FSharp.Compiler.Symbols + +[] +let ``Regression.Generic.3773a`` () = + assertTooltipContains "val M2: a: 'a -> obj" (markAtEndOfMarker "let rec M2<'a>(a:'a) = M2(a)" "let rec M") + +[] +let ``Regression.RecursiveDefinition.Generic.3773b`` () = + assertTooltipContains "val M1: a: int -> 'a" (markAtEndOfMarker "let rec M1<'a>(a:'a) = M1(0)" "let rec M") + +[] +let ``FrameworkClass`` () = + let source = "let l = new System.Collections.Generic.List()" + let marked = markAtEndOfMarker source "Generic.List" + assertTooltipContains "member Capacity: int\n" marked + assertTooltipContains "member Clear: unit -> unit\n" marked + assertTooltipDoesNotContain "get_Capacity" marked + assertTooltipDoesNotContain "set_Capacity" marked + assertTooltipDoesNotContain "get_Count" marked + assertTooltipDoesNotContain "set_Count" marked + +[] +let ``FrameworkClassNoMethodImpl`` () = + assertTooltipDoesNotContain + "System.Collections.ICollection.IsSynchronized" + (markAtEndOfMarker "let l = new System.Collections.Generic.LinkedList()" "Generic.LinkedList") + + assertTooltipContains + "LinkedList" + (markAtEndOfMarker "let l = new System.Collections.Generic.LinkedList()" "Generic.LinkedList") + +[] +let ``Regression.ExtensionMethods.DocComments.Bug6028`` () = + let source = + """open System.Linq +let rec query: System.Linq.IQueryable<_> = null +let _ = query.Al{caret}l""" + + assertTooltipContains "IQueryable.All" source + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + if m.XmlDocSig <> "M:System.Linq.Queryable.All``1(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})" then + failwithf "Unexpected XmlDocSig for query.All: %s" m.XmlDocSig + + let expectedAssembly = +#if NETCOREAPP + "System.Linq.Queryable.dll" +#else + "System.Core.dll" +#endif + let basename = m.Assembly.FileName |> Option.map System.IO.Path.GetFileName + + if basename <> Some expectedAssembly then + failwithf "Expected query.All to be defined in %s, but got %A" expectedAssembly basename + | sym -> failwithf "Expected a member symbol for query.All, but got %A" sym + +[] +let ``GenericDotNetMethodShowsComment`` () = + let source = "let _ = System.Linq.ParallelEnumerable.ElementA{caret}t" + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + let expected = + "M:System.Linq.ParallelEnumerable.ElementAt``1(System.Linq.ParallelQuery{``0},System.Int32" + + if not (m.XmlDocSig.Contains expected) then + failwithf "Unexpected XmlDocSig for ParallelEnumerable.ElementAt: %s" m.XmlDocSig + | sym -> failwithf "Expected a member symbol for ParallelEnumerable.ElementAt, but got %A" sym diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs new file mode 100644 index 00000000000..4d52736ead5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs @@ -0,0 +1,137 @@ +module FSharp.Compiler.Service.Tests.TooltipMembersTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +[] +let ``Regression.InDeclaration.Bug3176c`` () = + assertTooltipContains + "aaaa" + """type C = + val aa{caret}aa: int""" + +[] +let ``Declaration.CyclicalDeclarationDoesNotCrash`` () = + assertTooltipContains "type A" """type (*1*)A = int * A{caret} """ + +[] +let ``LongPaths`` () = + let source = + String.concat + "\n" + [ "let test0 = System.Console.In" + "let test0b = System.Collections.Generic.List()" + "let test0c = System.Collections.Generic.KeyNotFoundException()" + "type Test0d = System.Collections.Generic.List" + "type Test0e = System.Collections.Generic.KeyNotFoundException" ] + + let walk = EditorServiceAsserts.walk source + + walk "let test0 = " "System" "namespace System" + walk "let test0 = System." "Console" "Console =" + walk "let test0 = System.Console." "In" "System.Console.In" + walk "let test0 = System.Console." "In" "TextReader" + walk "let test0b = " "System" "namespace System" + walk "let test0b = System." "Collections" "namespace System.Collections" + walk "let test0b = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "let test0b = System.Collections.Generic." "List" "List()" + walk "let test0c = " "System" "namespace System" + walk "let test0c = System." "Collections" "namespace System.Collections" + walk "let test0c = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "let test0c = System.Collections.Generic." "KeyNotFoundException" "KeyNotFoundException()" + walk "type Test0d = " "System" "namespace System" + walk "type Test0d = System." "Collections" "namespace System.Collections" + walk "type Test0d = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "type Test0d = System.Collections.Generic." "List" "Generic.List" + walk "type Test0e = " "System" "namespace System" + walk "type Test0e = System." "Collections" "namespace System.Collections" + walk "type Test0e = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "type Test0e = System.Collections.Generic." "KeyNotFoundException" "Generic.KeyNotFoundException" + +[] +let ``AtEndOfLine`` () = + let (ToolTipText elements) = Checker.getTooltip "//{caret}" + + let meaningfulElements = + elements + |> List.filter (function + | ToolTipElement.None -> false + | _ -> true) + + match meaningfulElements with + | [] -> () + | _ -> failwithf "Expected an empty tooltip at the end of a comment line, but got: %A" elements + +#if !NETCOREAPP +let private getTooltipWithoutSystemDrawing (markedSource: string) = + getTooltipWithReferences + "MissingDependencyReferences" + [ fsCoreDefaultReference () + sysLib "mscorlib" + sysLib "System" + sysLib "System.Core" + sysLib "System.Windows.Forms" ] // System.Drawing.dll omitted on purpose (Bug 5409's missing transitive dependency) + markedSource + +[] +let ``MissingDependencyReferences.QuickInfo.Bug5409`` () = + let actual = + getTooltipWithoutSystemDrawing "let myFo{caret}rm = new System.Windows.Forms.Form()" + |> foldToolTip + + if not (actual.Contains "Form") then + failwithf "Expected tooltip to contain %A when System.Drawing is absent, but the actual tooltip was:\n%s" "Form" actual +#endif + +[] +let ``Regression.Bug4642`` () = + assertTooltipContains "int -> char" """ "AA".Ch{caret}ars """ + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_10`` () = + let source = "let _ = System.String.Form{caret}at" + assertTooltipContains "System.String.Format(" source + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + if m.XmlDocSig <> "M:System.String.Format(System.String,System.Object[])" then + failwithf "Unexpected XmlDocSig for String.Format: %s" m.XmlDocSig + + let expectedAssembly = +#if NETCOREAPP + "System.Runtime.dll" +#else + "mscorlib.dll" +#endif + let basename = m.Assembly.FileName |> Option.map System.IO.Path.GetFileName + + if basename <> Some expectedAssembly then + failwithf "Expected String.Format to be defined in %s, but got %A" expectedAssembly basename + | sym -> failwithf "Expected a member symbol for String.Format, but got %A" sym + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_13`` () = + assertTooltipContainsInOrder + [ "type KeyCollection<" + "member CopyTo" + """Represents the collection of keys in a . This class cannot be inherited.""" ] + "let _ = typeof.KeyColl{caret}ection>" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_14`` () = + assertTooltipContainsInOrder + [ "type ArgumentException" + "member Message" + "The exception that is thrown when one of the arguments provided to a method is not valid." + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_15`` () = + assertTooltipContainsInOrder + [ "property System.AppDomain.CurrentDomain: System.AppDomain" + """Gets the current application domain for the current .""" ] + "let _ = System.AppDomain.CurrentDom{caret}ain" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs new file mode 100644 index 00000000000..d5847b9eb08 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs @@ -0,0 +1,96 @@ +module FSharp.Compiler.Service.Tests.TooltipModulesTests + +open System +open Xunit +open FSharp.Compiler.EditorServices + +[] +let ``ModuleDefinition.ModuleNoNewLines`` () = + let source = + """module XXX +type t = C3 +module YYY = + type t = C4 +///Doc +module ZZZ = + type t = C5 """ + + assertTooltipContains "module XXX" (markAtEndOfMarker source "XX") + assertTooltipContainsInOrder [ "module YYY"; "from XXX" ] (markAtEndOfMarker source "YY") + assertTooltipContainsInOrder [ "module ZZZ"; "from XXX"; "Doc" ] (markAtEndOfMarker source "ZZ") + +[] +let ``TypeAndModuleReferences`` () = + let source = + String.concat + "\n" + [ "let test1 = List.length" + "let test2 = List.Empty" + "let test3 = (\"1\").Length" + "let test3b = (id \"1\").Length" ] + + walk source "let test1 = " "List" "module List" + walk source "let test1 = List." "length" "length" + walk source "let test2 = " "List" "Collections.List" + walk source "let test2 = List." "Empty" "List.Empty" + walk source "let test3 = (\"1\")." "Length" "String.Length" + walk source "let test3b = (id \"1\")." "Length" "String.Length" + +[] +let ``ModuleNameAndMisc`` () = + let source = + String.concat + "\n" + [ "module (*test3q*)MM3 =" + " let y = 2" + "let test4 = lock" + "let (*test5*) ffff xx = xx + 1" ] + + walk source "module (*test3q*)" "MM3" "module MM3" + walk source "let test4 = " "lock" "lock" + walk source "let (*test5*) " "ffff" "ffff" + +[] +let ``Regression.ModuleAlias.Bug3790a`` () = + let source = + """module ``Some`` = Microsoft.FSharp.Collections.List +module None = Microsoft.FSharp.Collections.List""" + + assertTooltipContains "module List" (markAtEndOfMarker source "module ``So") + assertTooltipContains "module List" (markAtEndOfMarker source "module No") + assertTooltipDoesNotContain "Option" (markAtEndOfMarker source "module ``So") + assertTooltipDoesNotContain "Option" (markAtEndOfMarker source "module No") + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_2`` () = + assertTooltipContainsInOrder + [ "module Inner"; "from"; "Outer"; "Comment" ] + """module Outer = + /// Comment + module Inner = + let x = 1 + +let _ = Outer.Inn{caret}er.x""" + +[] +let ``Automation.Regression.ModuleIdentifier.Bug2937`` () = + let source = "module XXX{caret}\ntype t = C3" + assertTooltipContains "module XXX" source + + for description in groupMainDescriptions (Checker.getTooltip source) do + if description.Contains "module XXX" && description.Contains "\n" then + failwithf "Expected the module identifier tooltip to be a single line, but it contained a newline:\n%s" description + +[] +let ``Automation.Regression.QuotedIdentifier.Bug3790`` () = + let source = + String.concat + "\n" + [ "module Test" + "module ``Some``(*Marker1*) = Microsoft.FSharp.Collections.List" + "let _ = ``Some``(*Marker2*).append [] []" ] + + assertTooltipContains "module List" (markAtStartOfMarker source "``(*Marker1*)") + assertTooltipDoesNotContain "Option.Some" (markAtStartOfMarker source "``(*Marker1*)") + assertTooltipContains "module List" (markAtStartOfMarker source "``(*Marker2*)") + assertTooltipDoesNotContain "Option.Some" (markAtStartOfMarker source "``(*Marker2*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs new file mode 100644 index 00000000000..48618eedc8e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs @@ -0,0 +1,54 @@ +module FSharp.Compiler.Service.Tests.TooltipPropertiesTests + +open Xunit + +let private propSource = + """namespace CountChocula + type BooBerry() = + let get() = "" + member source.Prop + with get() : int = 0 + and set(value:int) : unit = ()""" + +[] +let ``Regression.AccessorMutator.Bug4903a`` () = + assertTooltipDoesNotContain "string" (markAtEndOfMarker propSource "with g") + assertTooltipContains "int" (markAtEndOfMarker propSource "with g") + +[] +let ``Regression.AccessorMutator.Bug4903d`` () = + assertTooltipDoesNotContain + "string" + """namespace CountChocula + type BooBerry() = + member source.AMetho{caret}d() = () + member source.AProperty + with get() : int = 0 + and set(value:int) : unit = ()""" + +[] +let ``Regression.AccessorMutator.Bug4903b`` () = + assertTooltipDoesNotContain "seq" (markAtEndOfMarker propSource "and s") + assertTooltipContains "int" (markAtEndOfMarker propSource "and s") + +[] +let ``Regression.AccessorMutator.Bug4903c`` () = + assertTooltipContains "string" (markAtEndOfMarker propSource "let g") + +[] +[] +[] +[] +let ``Regression.AccessorMutator.Bug4903efg`` (marker: string) (expected: string) = + assertTooltipContains expected (markAtEndOfMarker propSource marker) + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_8`` () = + assertTooltipContainsInOrder + [ "property Foo.Property: string"; "A comment" ] + """type Foo = + /// A comment + static member Property + with get() = "" + +let x() = Foo.Prop{caret}erty""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs new file mode 100644 index 00000000000..97cbb16c89d --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs @@ -0,0 +1,245 @@ +module FSharp.Compiler.Service.Tests.TooltipQueriesTests + +open System +open System.IO +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.IO +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open TestFramework + +let private dataSourceCode = + """namespace DataSource +open System +open System.Xml.Linq + +type Product() = + let mutable id = 0 + let mutable name = "" + let mutable category = "" + let mutable price = 0M + let mutable unitsInStock = 0 + member x.ProductID with get() = id and set(v) = id <- v + member x.ProductName with get() = name and set(v) = name <- v + member x.Category with get() = category and set(v) = category <- v + member x.UnitPrice with get() = price and set(v) = price <- v + member x.UnitsInStock with get() = unitsInStock and set(v) = unitsInStock <- v + +module Products = + let getProductList() = + [ + Product(ProductID = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 39 ); + Product(ProductID = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000M, UnitsInStock = 17 ); + Product(ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000M, UnitsInStock = 13 ); + ] +""" + +let private assertQuickInfoInQuery (expected: string) (markedFile2: string) = + foldedProjectTooltip [ dataSourceCode ] [ sysLib "System.Xml.Linq" ] markedFile2 + |> assertFoldedTooltipContains true "query tooltip" expected + +[] +let ``Regression.ComputationExpressionMemberAppearingInQuickInfo`` () = + let source = + """module Test +let q2 = + query { + for p in [1;2] do + join cccccc in [3;4] on (p = cccccc) + yield ccc{caret}ccc + }""" + + assertTooltipDoesNotContain "Yield" source + assertTooltipContains "val cccccc: int" source + +[] +let ``QueryExpression.QuickInfoSmokeTest1`` () = + let source = """let q = query { for x in ["1"] do selec{caret}t x }""" + assertTooltipContains "custom operation: select" source + assertTooltipContains "custom operation: select ('Result)" source + assertTooltipContains "Calls" source + assertTooltipContains "Linq.QueryBuilder.Select" source + +[] +let ``QueryExpression.QuickInfoSmokeTest2`` () = + let source = """let q = query { for x in ["1"] do joi{caret}n y in ["2"] on (x = y); select (x,y) }""" + assertTooltipContains "custom operation: join" source + assertTooltipContains "join var in collection on (outerKey = innerKey)" source + assertTooltipContains "Calls" source + assertTooltipContains "Linq.QueryBuilder.Join" source + +[] +let ``QueryExpression.QuickInfoSmokeTest3`` () = + let source = """let q = query { for x in ["1"] do groupJoin{caret} y in ["2"] on (x = y) into g; select (x,g) }""" + assertTooltipContains "custom operation: groupJoin" source + assertTooltipContains "groupJoin var in collection on (outerKey = innerKey)" source + assertTooltipContains "Calls" source + assertTooltipContains "Linq.QueryBuilder.GroupJoin" source + +[] +let ``Query.WithError1.Bug196137`` () = + assertQuickInfoInQuery + "Product.ProductName: string" + """open DataSource +let products = Products.getProductList() +let sortedProducts = + query { + for p in products do + let x = p.ProductID + "a" + sortBy p.ProductName{caret} + select p + }""" + +[] +let ``Query.WithError2`` () = + assertQuickInfoInQuery + "custom operation: minBy ('Value)" + """open DataSource +let products = Products.getProductList() +let test = + query { + for p in products do + let x = p.ProductID + "1" + minBy{caret} p.UnitPrice + }""" + +[] +let ``Query.WithinLargeQuery`` () = + let source = + """open DataSource +let products = Products.getProductList() +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let largequery = + query { + for p in products do + sortBy p.ProductName + thenBy p.UnitPrice + thenByDescending p.Category + where (p.UnitsInStock < 100) + where (p.Category = "Condiments") + groupValBy(*Mark1*) p p.Category into g + let maxPrice = query { for x in g do maxBy(*Mark2*) x.UnitPrice } + let mostExpensiveProducts = query { for x in g do where (x.UnitPrice = maxPrice) } + select (g.Key, mostExpensiveProducts, query { + for n in numbers do + where (n%2 = 0) + where(*Mark3*) (n > 2) + where (n < 40) + select n}) + distinct(*Mark4*) + }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertQuickInfoInQuery "custom operation: groupValBy ('Value) ('Key)" (at "(*Mark1*)") + assertQuickInfoInQuery "custom operation: maxBy ('Value)" (at "(*Mark2*)") + assertQuickInfoInQuery "custom operation: where (bool)" (at "(*Mark3*)") + assertQuickInfoInQuery "custom operation: distinct" (at "(*Mark4*)") + +[] +let ``Query.ArgumentToQuery.OperatorError`` () = + let source = + """let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + orderBy (n.GetType()) + select n }""" + + assertTooltipContains "val n: int" (markAtStartOfMarker source "n.GetType()") + assertTooltipContains "System.Object.GetType() : System.Type" (markAtStartOfMarker source "Type()") + +[] +let ``Query.ArgumentToQuery.InNestedQuery`` () = + let source = + """open DataSource +let products = Products.getProductList() +let test1 = + query { + for p in products do + sortBy p.ProductName + select (p.ProductName, query { for f in products do + groupValBy(*Mark3*) f f.Category into g + let maxPrice = query { for x in g do maxBy x.UnitPrice } + let mostExpensiveProducts = query { for x in g do where(*Mark1*) (x.UnitPrice = maxPrice(*Mark2*)) } + select(*Mark4*) (g.Key, g)}) }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertQuickInfoInQuery "custom operation: where (bool)" (at "(*Mark1*)") + assertQuickInfoInQuery "val maxPrice: decimal" (at "(*Mark2*)") + assertQuickInfoInQuery "custom operation: groupValBy ('Value) ('Key)" (at "(*Mark3*)") + assertQuickInfoInQuery "custom operation: select ('Result)" (at "(*Mark4*)") + +[] +let ``Query.ComputationExpression.Method`` () = + let source = + """open System.Collections.Generic +let chars = ["A";"B";"C"] +type WorkflowBuilder() = + let yieldedItems = new List() + member this.Items = yieldedItems |> Array.ofSeq + member this.Yield(item) = yieldedItems.Add(item) + member this.YieldFrom(items : seq) = + items |> Seq.iter (fun item -> yieldedItems.Add(item.ToUpper())) + () + member this.Combine(f, g) = g + member this.Delay (f : unit -> 'a) = + f() + member this.Zero() = () + member this.Return _ = this.Items +let computationExpreQuery = + query { + for char in chars do + let workflow = new WorkflowBuilder() + let result = + workflow { + yield "foo" + yield "bar" + yield! [| "a"; "b"; "c" |] + return () + } + let t = workflow.Combine(*Mark1*)("a","b") + let d = workflow.Zero(*Mark2*)() + where (result |> Array.exists(fun i -> i = char)) + yield char + }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertTooltipContains "member WorkflowBuilder.Combine: f: 'b0 * g: 'c1 -> 'c1" (at "(*Mark1*)") + assertTooltipContains "member WorkflowBuilder.Zero: unit -> unit" (at "(*Mark2*)") + +[] +let ``Query.ComputationExpression.CustomOp`` () = + let source = + """open System +open Microsoft.FSharp.Quotations + +type EventBuilder() = + member _.For(ev:IObservable<'T>, loop:('T -> #IObservable<'U>)) : IObservable<'U> = failwith "" + member _.Yield(v:'T) : IObservable<'T> = failwith "" + member _.Quote(v:Quotations.Expr<'T>) : Expr<'T> = v + member _.Run(x:Expr<'T>) = Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation x :?> 'T + + [] + member _.Where (x, [] f) = Observable.filter f x + + [] + member _.Select (x, [] f) = Observable.map f x + + [] + member inline _.ScanSumBy (source, [] f : 'T -> 'U) : IObservable<'U> = Observable.scan (fun a b -> a + f b) LanguagePrimitives.GenericZero<'U> source + +let myquery = EventBuilder() +let f = new Event() +let e1 = + myquery { for x in f.Publish do + myWhere(*Mark1*) (fst x < 100) + scanSumBy(*Mark2*) (snd x) + }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertTooltipContains "custom operation: myWhere (bool)" (at "(*Mark1*)") + assertTooltipContains "Calls EventBuilder.Where" (at "(*Mark1*)") + assertTooltipContains "custom operation: scanSumBy ('U)" (at "(*Mark2*)") + assertTooltipContains "Calls EventBuilder.ScanSumBy" (at "(*Mark2*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs new file mode 100644 index 00000000000..3a12966746e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs @@ -0,0 +1,94 @@ +module FSharp.Compiler.Service.Tests.TooltipRecordsTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +let private assertTooltipTrimmedContainsInFsFile (expected: string) (markedSource: string) = + let actual = foldedTooltip FsFile markedSource + let trimmed = actual.Replace("\r", "").Replace("\n", "") + + if not (trimmed.Contains expected) then + failwithf "Expected newline-stripped .fs-file tooltip to contain %A, but the actual tooltip was:\n%s" expected actual + +[] +[] + [] + member x._Print = x.Element.ToString() +let u = { Element = "abc" } +""", + "member _Print", "")>] +[] + member x.Print1 = x.Element.ToString() + member x.Print2 = x.Element.ToString() +let u = { Element = "abc" } +""", + "member Print1", "member Print2")>] +let ``Hidden record members are omitted from the type tooltip`` (source: string) (notExpected: string) (alsoExpected: string) = + let marked = markAtStartOfMarker source "ypeU =" + assertTooltipDoesNotContain notExpected marked + + if alsoExpected <> "" then + assertTooltipContains alsoExpected marked + +[] +let ``TypeRecordQuickInfo`` () = + let source = + """namespace NS + type Re(*MarkerRecord*) = { X : int } """ + + assertTooltipTrimmedContainsInFsFile "type Re = { X: int }" (markAtStartOfMarker source "(*MarkerRecord*)") + +[] +let ``Regression.InDeclaration.Bug3176a`` () = + let source = """type T<'a> = { aaaa : 'a; bbbb : int } """ + assertTooltipContains "aaaa: 'a" (markAtEndOfMarker source "aa") + +[] +let ``IdentifiersForFields`` () = + let source = + String.concat "\n" [ "type TestType9 = { XXX : int }"; "let test11 = { XXX = 1 }" ] + + walk source "type TestType9 = { " "XXX" "XXX: int" + walk source "let test11 = { " "XXX" "XXX" + +[] +let ``ArgumentAndPropertyNames`` () = + let source = + String.concat + "\n" + [ "type R = { mutable AAA : int }" + " static member M() = { AAA = 1 }" + "let test13 = R.M(AAA=3)" + "type R2() = " + " static member M() = System.Reflection.InterfaceMapping()" + "" + "let test14 = R2.M(InterfaceMethods= [| |])" + "" + "let test15 = new System.Reflection.AssemblyName(Name=\"Foo\")" + "let test16 = new System.Reflection.AssemblyName(assemblyName=\"Foo\")" ] + + walk source "let test13 = R.M(" "AAA" "R.AAA: int" + walk source "let test14 = R2.M(" "InterfaceMethods" "field System.Reflection.InterfaceMapping.InterfaceMethods" + walk source "let test15 = new System.Reflection.AssemblyName(" "Name" "property System.Reflection.AssemblyName.Name" + walk source "let test16 = new System.Reflection.AssemblyName(" "assemblyName" "argument assemblyName" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_7`` () = + assertTooltipContainsInOrder + [ "Record.field: int"; "A comment" ] + """type Record = { + /// A comment + field : int + } + +let record = {field = 1} +let x() = record.fie{caret}ld""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs new file mode 100644 index 00000000000..a64704cd2b7 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs @@ -0,0 +1,203 @@ +module FSharp.Compiler.Service.Tests.TooltipTypeProvidersTests + +open Xunit + +[] +let ``TypeProviders.NestedTypesOrder`` () = + assertTooltipContainsInOrder + [ "A"; "X"; "Z" ] + """type t = N1.TypeWithNestedTypes{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.Comment`` () = + assertTooltipContains + "This is a synthetic type created by me!" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.WithLongComment`` () = + assertTooltipContains + "This is a synthetic type created by me!. Which is used to test the tool tip of the typeprovider type to check if it shows the right message or not." + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.WithNullComment`` () = + assertTooltipContains + "type T =\n new: unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.WithEmptyComment`` () = + assertTooltipContains + "type T =\n new : unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic type Localized! ኤፍ ሻርፕ" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.Comment`` () = + assertTooltipContains + "This is a synthetic .ctor created by me for N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.WithLongComment`` () = + assertTooltipContains + "This is a synthetic .ctor created by me for N.T. Which is used to test the tool tip of the typeprovider Constructor to check if it shows the right message or not." + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.WithNullComment`` () = + assertTooltipContains + "N.T() : N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.WithEmptyComment`` () = + assertTooltipContains + "N.T() : N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic .ctor Localized! ኤፍ ሻርፕ for N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.Comment`` () = + assertTooltipContains + "This is a synthetic *event* created by me for N.T" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic *event* Localized! ኤፍ ሻርፕ for N.T" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.ParamsAttributeTest`` () = + assertTooltipContains + "[] separator" + """let t = "a".Spl{caret}it('c', 'd')""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.WithLongComment`` () = + assertTooltipContains + "This is a synthetic *event* created by me for N.T. Which is used to test the tool tip of the typeprovider Event to check if it shows the right message or not.!" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.WithNullComment`` () = + assertTooltipContains + "member N.T.Event1: IEvent" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.WithEmptyComment`` () = + assertTooltipContains + "member N.T.Event1: IEvent" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.Comment`` () = + assertTooltipContains + "This is a synthetic *method* created by me!!" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic *method* Localized! ኤፍ ሻርፕ" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.WithLongComment`` () = + assertTooltipContains + "This is a synthetic *method* created by me!!. Which is used to test the tool tip of the typeprovider Method to check if it shows the right message or not.!" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.WithNullComment`` () = + assertTooltipContains + "N.T.M() : int array" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.WithEmptyComment`` () = + assertTooltipContains + "N.T.M() : int array" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.Comment`` () = + assertTooltipContains + "This is a synthetic *property* created by me for N.T" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic *property* Localized! ኤፍ ሻርፕ for N.T" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.WithLongComment`` () = + assertTooltipContains + "This is a synthetic *property* created by me for N.T. Which is used to test the tool tip of the typeprovider Property to check if it shows the right message or not.!" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.WithNullComment`` () = + assertTooltipContains + "property N.T.StaticProp: decimal" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.WithEmptyComment`` () = + assertTooltipContains + "property N.T.StaticProp: decimal" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.StaticParameters.Correct`` () = + assertTooltipContains + "type foo = N1.T" + """type foo{caret} = N1.T< const "Hello World",2>""" + +[] +let ``TypeProvider.StaticParameters.Negative.Invalid`` () = + assertTooltipContains + "type foo" + """type foo{caret} = N1.T< const 100,2>""" + +[] +let ``TypeProvider.StaticParameters.XmlComment`` () = + assertTooltipContains + "XMLComment" + """///XMLComment +type foo{caret} = N1.T< const "Hello World",2>""" + +[] +let ``TypeProvider.StaticParameters.QuickInfo.OnTheErasedType`` () = + assertTooltipContains + "type TTT = Samples.FSharp.RegexTypeProvider.RegexTyped<...>\nFull name: File1.TTT" + """type TTT{caret} = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)">""" + +[] +let ``TypeProvider.StaticParameters.QuickInfo.OnNestedErasedTypeProperty`` () = + assertTooltipContains + "property Samples.FSharp.RegexTypeProvider.RegexTyped<...>.MatchType.AreaCode: System.Text.RegularExpressions.Group" + """type T = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)"> +let reg = T() +let r = reg.Match("425-123-2345").A{caret}reaCode.Value""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs new file mode 100644 index 00000000000..e875a276073 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs @@ -0,0 +1,464 @@ +module FSharp.Compiler.Service.Tests.TooltipTypesTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +[] +let ``NestedTypesOrder`` () = + assertTooltipContainsInOrder + [ "GetHashCode"; "GetObjectValue" ] + (markAtStartOfMarker "type t = System.Runtime.CompilerServices.RuntimeHelpers(*M*)" "(*M*)") + +[] +let ``QuickInfo.HideBaseClassMembersTP`` () = + assertTooltipContains + "type HiddenBaseMembersTP =\n inherit TPBaseTy" + (markAtStartOfMarker "type foo = HiddenMembersInBaseClass.HiddenBaseMembersTP(*Marker*)" "MembersTP(*Marker*)") + +[] +let ``QuickInfo.OverridenMethods`` () = + let source = + """ +type A() = + abstract member M: unit -> unit + /// 1234 + default this.M() = () + +type AA() = + inherit A() + /// 5678 + override this.M() = () +let x = new AA() +x.M() + +let y = new A() +y.M() +""" + + assertTooltipContains "5678" (markAtEndOfMarker source "x.M") + assertTooltipContains "1234" (markAtEndOfMarker source "y.M") + +[] +let ``QuickInfoForTypesWithHiddenRepresentation`` () = + let signatureListing = + "type Async =\n static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * objnull -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)\n static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate and 'Del: not null)\n static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async\n static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload\n static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async\n static member CancelDefaultToken: unit -> unit\n static member Catch: computation: Async<'T> -> Async>\n static member Choice: computations: Async<'T option> seq -> Async<'T option>\n static member FromBeginEnd: beginAction: (AsyncCallback * objnull -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads\n static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>\n ..." + + assertTooltipContainsInOrder + [ signatureListing; "Full name: Microsoft.FSharp.Control.Async" ] + (markAtEndOfMarker "let x = Async.AsBeginEnd\n1" "Asyn") + +[] +let ``GetterSetterInsideInterfaceImpl.ThisOnceAsserted`` () = + assertTooltipContains + "Operators.id" + """ +type IFoo = + abstract member X: int with get,set + +type Bar = + interface IFoo with + member this.X + with get() = 42 // hello + and set(v) = id{caret}() """ + +[] +let ``Regression.FieldRepeatedInToolTip.Bug3538`` () = + assertIdentifierInTooltipExactlyOnce + "Explicit" + """ +open System.Runtime.InteropServices +[] +type A() = + [] + val mutable x : int""" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_1`` () = + assertCompletionItemTooltipContainsInOrder + "Overload" + [ "static member MyType.Overload: unit -> int" + "static member MyType.Overload: x: int -> int" + "Hello" ] + """type MyType = + /// Hello + static member Overload() = 0 + /// Hello2 + static member Overload(x:int) = 0 + /// Hello3 + static member NonOverload() = 0 +let x() = MyType.{caret}""" + +[] +let ``Regression.Class.Printing.FSharp.Classes.Bug4624`` () = + let source = + """type F1() = + class + inherit System.Windows.Forms.Form() + abstract AAA : int with get + abstract ZZZ : int with get + abstract AAA : bool with set + val x : F1 + static val x : F1 + static member A() = 12 + member this.B() = 12 + static member C() = 12 + member this.D() = 12 + member this.D with get() = 12 and set(12) = () + member this.D(x:int,y:int) = 12 + member this.D(x:int) = 12 + member this.D x y z = [1;x;y;z] + override this.ToString() = "" + interface System.IDisposable with + override this.Dispose() = () + end + end +type A1 = F1""" + + assertTooltipContainsInOrder + [ "type F1 =" +#if !NETCOREAPP + " inherit Form" +#endif + " interface IDisposable" + " new: unit -> F1" + " val x: F1" + " member B: unit -> int" + " override ToString: unit -> string" + " static member A: unit -> int" + " static member C: unit -> int" + " abstract AAA: int" + " member D: int" + " ..." ] + (markAtEndOfMarker source "type A1 = F1") + +[] +let ``Automation.Regression.BeforeAndAfterIdentifier.Bug4371`` () = + let baseSrc = + """module Test +let f arg1 (arg2, arg3, arg4) arg5 = 42 +let goo a = f 12 a + +type printer = System.Console +let z = printer.BufferWidth""" + + let fSrc = baseSrc.Replace("let goo a = f 12 a", "let goo a = f{caret} 12 a") + assertTooltipContains "Full name: Test.f" fSrc + assertTooltipContains "val f" fSrc + + assertTooltipContains + "property System.Console.BufferWidth: int" + (baseSrc.Replace("let z = printer.BufferWidth", "let z = printer.BufferWidth{caret}")) + + assertTooltipContains + "Full name: Test.printer" + (baseSrc.Replace("let z = printer.BufferWidth", "let z = printer{caret}.BufferWidth")) + +[] +let ``Automation.Regression.ConstructorWithSameNameAsType.Bug2739`` () = + let source = + """namespace AA +module AA = + type AA = | AA(*Marker1*) = 1 + | BB = 2 +type BB = { BB(*Marker2*) : string; }""" + + assertTooltipContainsInFsFile "AA.AA: AA" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsInFsFile "BB.BB: string" (markAtStartOfMarker source "(*Marker2*)") + +[] +let ``Automation.Regression.EventImplementation.Bug5471`` () = + let source = + """namespace regressiontest +open System.ComponentModel + +type CommandReference() = + let evt = Event() + + interface INotifyPropertyChanged with + [] + member x.PropertyChanged(*Marker*) = evt.Publish""" + + let marked = markAtStartOfMarker source "(*Marker*)" + assertTooltipContainsInFsFile "override CommandReference.PropertyChanged: IEvent" marked + assertTooltipContainsInFsFile "regressiontest.CommandReference.PropertyChanged" marked + +[] +let ``Automation.ExtensionMethod`` () = + let source = + """namespace TestQuickinfo + +module BCLExtensions = + type System.Random with + /// BCL class Extension method + member this.NextDice() = this.Next() + 1 + /// new BCL class Extension method with overload + member this.NextDice(a : bool) = this.Next() + 1 + /// existing BCL class Extension method with overload + member this.Next(a : bool) = this.Next() + 1 + /// BCL class Extension property + member this.DiceValue with get() = 6 + + type System.ConsoleKeyInfo with + /// BCL struct extension method + member this.ExtensionMethod() = 100 + /// BCL struct extension property + member this.ExtensionProperty with get() = "Foo" + +module OwnCode = + /// fs class + type FSClass() = + class + /// fs class method original + member this.Method(a:string) = "" + /// fs class property original + member this.Prop with get(a:string) = "" + end + + /// fs struct + type FSStruct(x:int) = + struct + end + +module OwnCodeExtensions = + type OwnCode.FSClass with + /// fs class extension method + member this.ExtensionMethod() = 100 + /// fs class extension property + member this.ExtensionProperty with get() = "Foo" + /// fs class method extension overload + member this.Method(a:int) = "" + /// fs class property extension overload + member this.Prop with get(a:int) = "" + + type OwnCode.FSStruct with + /// fs struct extension method + member this.ExtensionMethod() = 100 + /// fs struct extension property + member this.ExtensionProperty with get() = "Foo" + +module BCLClass = + open BCLExtensions + let rnd = new System.Random() + rnd.DiceValue(*Marker11*) |>ignore + rnd.NextDice(*Marker12*)() |>ignore + rnd.NextDice(*Marker13*)(true) |>ignore + rnd.Next(*Marker14*)(true) |>ignore + +module BCLStruct = + open BCLExtensions + let cki = new System.ConsoleKeyInfo() + cki.ExtensionMethod(*Marker21*) |>ignore + cki.ExtensionProperty(*Marker22*) |>ignore + +module OwnClass = + open OwnCode + open OwnCodeExtensions + let rnd = new FSClass() + rnd.ExtensionMethod(*Marker31*) |>ignore + rnd.ExtensionProperty(*Marker32*) |>ignore + rnd.Method(*Marker33*)("") |>ignore + rnd.Method(*Marker34*)(6) |>ignore + rnd.Prop(*Marker35*)("") |>ignore + rnd.Prop(*Marker36*)(6) |>ignore + +module OwnStruct = + open OwnCode + open OwnCodeExtensions + let cki = new FSStruct(100) + cki.ExtensionMethod(*Marker41*) |>ignore + cki.ExtensionProperty(*Marker42*) |>ignore""" + + let assertAt marker sig' doc = + let marked = markAtStartOfMarker source marker + assertTooltipContainsInFsFile sig' marked + assertTooltipContainsInFsFile doc marked + + assertAt "(*Marker11*)" "property System.Random.DiceValue: int" "BCL class Extension property" + assertAt "(*Marker12*)" "member System.Random.NextDice: unit -> int" "BCL class Extension method" + assertAt "(*Marker13*)" "member System.Random.NextDice: a: bool -> int" "new BCL class Extension method with overload" + assertAt "(*Marker14*)" "member System.Random.Next: a: bool -> int" "existing BCL class Extension method with overload" + assertAt "(*Marker21*)" "member System.ConsoleKeyInfo.ExtensionMethod: unit -> int" "BCL struct extension method" + assertAt "(*Marker22*)" "System.ConsoleKeyInfo.ExtensionProperty: string" "BCL struct extension property" + assertAt "(*Marker31*)" "member FSClass.ExtensionMethod: unit -> int" "fs class extension method" + assertAt "(*Marker32*)" "FSClass.ExtensionProperty: string" "fs class extension property" + assertAt "(*Marker33*)" "member FSClass.Method: a: string -> string" "fs class method original" + assertAt "(*Marker34*)" "member FSClass.Method: a: int -> string" "fs class method extension overload" + assertAt "(*Marker35*)" "property FSClass.Prop: string -> string" "fs class property original" + assertAt "(*Marker36*)" "property FSClass.Prop: int -> string" "fs class property extension overload" + assertAt "(*Marker41*)" "member FSStruct.ExtensionMethod: unit -> int" "fs struct extension method" + assertAt "(*Marker42*)" "FSStruct.ExtensionProperty: string" "fs struct extension property" + +[] +let ``Automation.Regression.GenericFunction.Bug2868`` () = + let marked = + markAtStartOfMarker + """module Test +let F (f :_ -> float<_>) = fun x -> f (x+1.0) +let rec Gen<[] 'u> (f:float<'u> -> float<'u>) = + Gen(*Marker*)(F f)""" + "(*Marker*)" + + assertTooltipContains "val Gen: f: (float -> float) -> 'a" marked + assertTooltipDoesNotContain "Exception" marked + assertTooltipDoesNotContain "thrown" marked + +[] +let ``Automation.Regression.NamesArgument.Bug3818`` () = + assertTooltipContains + "property System.AttributeUsageAttribute.AllowMultiple: bool" + (markAtStartOfMarker + """module m +[] +type T = class + end""" + "(*Marker1*)") + +[] +let ``Automation.OnUnitsOfMeasure`` () = + let source = + """namespace TestQuickinfo + +module TestCase1 = + [] + /// this type represents kilogram in UOM + type kg + let mass(*Marker11*) = 2.0 + +module TestCase2 = + [] + /// use Set as the type name of UoM + type Set + + let v1 = [1.0 .. 2.0 .. 5.0] |> Seq.item 1 + + (if v1 = 3.0 then 0 else 1) |> ignore + + let twoSets = 2.0 + + [1.0] + |> Set.ofList + |> Set(*Marker22*).isEmpty + |> ignore""" + + assertTooltipContainsInFsFile "val mass: float" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.TestCase1.mass" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "inherits: System.ValueType" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "[]" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "type kg" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "this type represents kilogram in UOM" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.TestCase1.kg" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "[]" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "type Set" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "use Set as the type name of UoM" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.TestCase2.Set" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "module Set" (markAtStartOfMarker source "(*Marker22*)") + assertTooltipContainsInFsFile "from Microsoft.FSharp.Collections" (markAtStartOfMarker source "(*Marker22*)") + assertTooltipContainsInFsFile "Functional programming operators related to the Set<_> type." (markAtStartOfMarker source "(*Marker22*)") + +[] +let ``Automation.Setter`` () = + let source = + """type T() = + member this.XX + with set ((a:int), (b:int), (c:int)) = () + +(new T()).XX(*Marker1*) <- (1,2,3) + +type IFoo = interface + abstract foo : int -> int + end +let i : IFoo = Unchecked.defaultof +i.foo(*Marker2*) |> ignore + +type Rec = { bar:int->int->int } +let r = {bar = fun x y -> x + y } + +r.bar(*Marker3*) 1 2 |>ignore + +type M() = + member this.baz x y = x + y +let m = new M() +m.baz(*Marker3*) 1 2 |>ignore + +type T2() = + member this.Foo(a,b) = "" +let t = new T2() +t.Foo(*Marker4*)(1,2) |>ignore + +let foo (x:int) (y:int) : int = 1 +foo(*Marker5*) 2 3 |> ignore""" + + assertTooltipContains "T.XX: int * int * int" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipDoesNotContain "->" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContains "IFoo.foo: int -> int" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContains "Rec.bar: int -> int -> int" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContains "T2.Foo: a: 'a * b: 'b -> string" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContains "val foo: int -> int -> int" (markAtStartOfMarker source "(*Marker5*)") + +[] +let ``Automation.Regression.TypeInferenceScenarios.Bug2362_3538`` () = + let source = + """module Test.Module1 + +open System +open System.Diagnostics +open System.Runtime.InteropServices + +#nowarn "9" + +let append m(*Marker1*) n(*Marker2*) = fun ac(*Marker3*) -> m (n ac) + +type Foo() as this(*Marker4*) = + do this(*Marker5*) |> ignore + member this.Bar() = + this(*Marker6*) |> ignore + () + +[] +type A = + [] + val mutable x : int + new () = { } + member this.Prop = this.x + +let x = new (*Marker7*)A()""" + + assertTooltipContains "val m: ('a -> 'b)" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContains "val n: ('c -> 'a)" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContains "val ac: 'c" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContains "val this: Foo" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContains "val this: Foo" (markAtStartOfMarker source "(*Marker5*)") + assertTooltipContains "val this: Foo" (markAtStartOfMarker source "(*Marker6*)") + + let mSrc7 = source.Replace("new (*Marker7*)A()", "new A{caret}()") + assertTooltipContains "type A =" mSrc7 + assertTooltipContains "val mutable x: int" mSrc7 + +[] +let ``Automation.Regression.XmlDocCommentsOnExtensionMembers.Bug138112`` () = + let source = + """module Module1 = + type T() = + /// XmlComment M1 + member this.M1() = () + type T with + /// XmlComment M2 + member this.M2() = () + module public Extension = + type T with + /// XmlComment M3 + member this.M3() = () +open Module1 +open Extension + +let x1 = T().M1(*Marker1*)() +let x2 = T().M2(*Marker2*)() +let x3 = T().M3(*Marker3*)()""" + + assertTooltipContains "XmlComment M1" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContains "XmlComment M2" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContains "XmlComment M3" (markAtStartOfMarker source "(*Marker3*)") diff --git a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs index 5bee4573952..5c53e7879ee 100644 --- a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs @@ -370,21 +370,6 @@ let getCheckResults source options = checkResults -let taggedTextsToString (t: TaggedText array) = - t - |> Array.map (fun taggedText -> taggedText.Text) - |> String.concat "" - -let assertAndExtractTooltip (ToolTipText(items)) = - Assert.Equal(1,items.Length) - match items[0] with - | ToolTipElement.Group [ singleElement ] -> - let toolTipText = - singleElement.MainDescription - |> taggedTextsToString - toolTipText, singleElement.XmlDoc, singleElement.Remarks |> Option.map taggedTextsToString - | _ -> failwith $"Expected group, got {items[0]}" - let assertAndGetSingleToolTipText items = let text,_xml,_remarks = assertAndExtractTooltip items text diff --git a/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs b/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs index 22393f98607..dff8364704f 100644 --- a/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs +++ b/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs @@ -1,7 +1,6 @@ module FSharp.Compiler.Service.Tests.TypeChecker.Obsolete open FSharp.Compiler.Service.Tests -open FSharp.Compiler.Symbols open FSharp.Test.Assert open Xunit diff --git a/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs b/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs index 343009b8db4..4f24fb873f0 100644 --- a/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs @@ -1,7 +1,10 @@ -module FSharp.Compiler.Service.Tests.TypeChecker.TypeCheckerRecoveryTests +module FSharp.Compiler.Service.Tests.TypeChecker.TypeCheckerRecoveryTests open FSharp.Compiler.Service.Tests +open FSharp.Compiler.Symbols open FSharp.Compiler.Text +open FSharp.Compiler.Service.Tests.CompletionTests +open FSharp.Compiler.Service.Tests.TooltipTests open FSharp.Test.Assert open Xunit @@ -27,7 +30,6 @@ do "(3,12--3,13)", 39 ] - [] let ``Tuple 01`` () = let _, checkResults = getParseAndCheckResults """ @@ -44,7 +46,6 @@ Math.Max(a,) assertHasSymbolUsages ["Max"] checkResults - [] let ``Tuple 02`` () = let _, checkResults = getParseAndCheckResults """ @@ -83,112 +84,300 @@ T.M{caret} "" """ module Expressions = + [] + [] + [] + [] + [] + let ``Method type`` (name: string) (source: string) = + assertHasSymbolUsageAtCaret name source + +module Patterns = + [] + [ () + """)>] + [ () + """)>] + [] + [] + [ () + """)>] + [] + [] + let ``Enum - Type`` (source: string) = + assertHasSymbolUsageAtCaret "E" source + +module ErrorRecovery = + + [] + [] + [] + [] + [] + let ``Bug4881 - member completion after dot in elif on broken code`` (source: string) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames ["Split"] info + [] - let ``Method type 01`` () = - assertHasSymbolUsageAtCaret "ToString" """ -if true then - "".ToString{caret} + let ``NotFixing4538_1 - completion offers type after partial 'new MyT'`` () = + let info = Checker.getCompletionInfo """ +type MyType() = + override x.ToString() = "" +let Main() = + let _ = new MyT{caret} + () """ - + assertHasItemWithNames ["MyType"] info + + [] + [] + [] + let ``NotFixing4538_2_3 - completion offers type after partial 'MyT'`` (source: string) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames ["MyType"] info [] - let ``Method type 02`` () = - assertHasSymbolUsageAtCaret "M" """ -type T = - static member M() = "" - -if true then - T.M{caret} + let ``Bug4538_2 - completion offers type after a preceding valid binding`` () = + let info = Checker.getCompletionInfo """ +type MyType() = + override x.ToString() = "" +let Main() = + let x = MyType() + let _ = MyT{caret} """ + assertHasItemWithNames ["MyType"] info [] - let ``Method type 03`` () = - assertHasSymbolUsageAtCaret "M" """ -type T = - static member M(i: int) = "" - static member M(s: string) = "" - -if true then - T.M{caret} + let ``Bug4538_5 - completion offers type after partial 'MyT' in use binding`` () = + let info = Checker.getCompletionInfo """ +type MyType() = + override x.ToString() = "" +let Main() = + use x = null + use _ = MyT{caret} """ + assertHasItemWithNames ["MyType"] info [] - let ``Method type 04`` () = - assertHasSymbolUsageAtCaret "GetHashCode" """ -let o: obj = null -if true then - o.GetHashCode{caret} + let ``5878_1 - member data tip available for Module dot at end of file`` () = + let info = Checker.getCompletionInfo """ +module Module = + /// Union comment + type Union = + /// Case comment + | Case of int +Module.{caret} """ + let caseItem = + info.Items + |> Array.find (fun item -> item.NameInCode = "Case") -module Patterns = - [] - let ``Enum - Type 01`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + let description, xmlDoc, _ = assertAndExtractTooltip caseItem.Description -match E.A with -| E{caret}.A -> () -""" + Assert.Contains("union case Module.Union.Case: int -> Module.Union", description) - [] - let ``Enum - Type 02`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + match xmlDoc with + | FSharpXmlDoc.FromXmlText t -> + Assert.Contains("Case comment", String.concat "\n" t.UnprocessedLines) + | other -> failwith $"Expected FSharpXmlDoc.FromXmlText, got {other}" -match E.A with -| E{caret} -> () -""" +module ExhaustivelyScrutinize = [] - let ``Enum - Type 03`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 - -match E.A with -| E{caret} + let ``ThisOnceAsserted - if/elif/else returning malformed tuples`` () = + let _, checkResults = getParseAndCheckResults """ +let F() = + if true then [], + elif true then [],"" + else [],"" """ + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(4,4--4,8)", 58 + "(3,19--3,20)", 3100 + ] [] - let ``Enum - Type 04`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 - -match E.A with -| E{caret}. + let ``ThisOnceAssertedToo - interface implementation`` () = + let _, checkResults = getParseAndCheckResults """ +type C() = + member this.F() = () + interface System.IComparable with + member _.CompareTo(v:obj) = 1 """ - - [] - let ``Enum - Type 05`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(2,5--2,6)", 343 + ] -match E.A with -| E{caret}. -> () + [] + let ``ThisOnceAssertedThree - property with get and set`` () = + let _, checkResults = getParseAndCheckResults """ +type Foo = + { mutable Data: string } + member x.XmlDocSig + with get() = x.Data + and set(v) = x.Data <- v """ + dumpDiagnosticNumbers checkResults |> shouldEqual [] - [] - let ``Enum - Type 06`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 - -match E.A with -| E{caret}.B + [] + let ``ThisOnceAssertedFour - unfinished new`` () = + let _, checkResults = getParseAndCheckResults """ +let y=new +let z=4 """ + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(3,0--3,3)", 10 + ] [] - let ``Enum - Type 07`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + let ``ThisOnceAssertedFive - type application with quotation token`` () = + let _, checkResults = getParseAndCheckResults """ +CSV.File<@"File1.txt">.[0]. +""" + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(2,10--2,21)", 10 + "(2,10--2,21)", 1241 + "(2,21--2,22)", 3156 + "(2,0--2,3)", 39 + ] -match E.A with -| E{caret}. + [] + let ``Bug2277 - open of non-existent namespace`` () = + let _, checkResults = getParseAndCheckResults """ +open Microsoft.FSharp.Plot.Excel +open Microsoft.FSharp.Plot.Interactive +let ps = [| (1.,"c"); (-2.,"p") |] +plot (Bars(ps)) +let xs = [| 1.0 .. 20.0 |] +let ys = [| 2.0 .. 21.0 |] +let pp= plot(Area(xs,ys)) +""" + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(2,22--2,26)", 39 + "(3,22--3,26)", 39 + "(5,0--5,4)", 39 + "(8,8--8,12)", 39 + ] -() + [] + let ``Bug2283 - missing reference and nested generic classes`` () = + let _, checkResults = getParseAndCheckResults """ +#r "NestedClasses.dll" +//753 atomType -> atomType DOT path typeArgs +let specificIdent (x : RootNamespace.ClassOfT.NestedClassOfU) = x +let x = new RootNamespace.ClassOfT.NestedClassOfU() +if specificIdent x <> x then exit 1 +exit 0 """ +#if NETCOREAPP + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(4,23--4,36)", 39 + "(5,12--5,25)", 39 + ] +#else + dumpDiagnosticNumbers checkResults + |> List.distinct + |> List.sort + |> shouldEqual [ + "(2,0--2,22)", 84 + "(4,23--4,36)", 39 + "(5,12--5,25)", 39 + ] +#endif diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs index b2edb2a68c7..c36379acdb4 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs @@ -268,1043 +268,58 @@ type UsingMSBuild() as this = let completions = DotCompletionAtStartOfMarker file marker AssertCompListIsEmpty(completions) - [] - member this.``AutoCompletion.ObjectMethods``() = - let code = - [ - "type DU1 = DU_1" - - "[]" - "type DU2 = DU_2" - - "[]" - "type DU3 =" - " | DU_3" - " with member this.Equals(b : string) = 1" - - "[]" - "type DU4 =" - " | DU_4" - " with member this.GetHashCode(b : string) = 1" - - - "module Extensions =" - " type System.Object with" - " member this.ExtensionPropObj = 42" - " member this.ExtensionMethodObj () = 42" - - "open Extensions" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - let test tail marker expected notExpected = - let code = code @ [tail] - ReplaceFileInMemory file code - MoveCursorToEndOfMarker(file,marker) - - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, expected) - AssertCompListDoesNotContainAny(completions, notExpected) - - test "obj()." ")." ["Equals"; "ExtensionPropObj"; "ExtensionMethodObj"] [] - test "System.Object." "Object." ["Equals"; "ReferenceEquals"] [] - test "System.String." "String." ["Equals"] [] - test "DU_1." "DU_1." ["Equals"; "GetHashCode"; "ExtensionMethodObj"; "ExtensionPropObj"] [] - test "DU_2." "DU_2." ["ExtensionPropObj"; "ExtensionMethodObj"] ["Equals"; "GetHashCode"] // no equals\gethashcode - test "DU_3." "DU_3." ["ExtensionPropObj"; "ExtensionMethodObj"; "Equals"] ["GetHashCode"] // no gethashcode, has equals defined in DU3 type - test "DU_4." "DU_4." ["ExtensionPropObj"; "ExtensionMethodObj"; "GetHashCode"] ["Equals"] // no equals, has gethashcode defined in DU4 type - [] - member this.``AutoCompletion.BeforeThis``() = - let code = - [ - [ - "type A() =" - " member _.X = ()" - " member this." - ] - [ - "type A() =" - " member _.X = ()" - " member private this." - ] - [ - "type A() =" - " member _.X = ()" - " member public this." - ] - [ - "type A() =" - " member _.X = ()" - " member internal this." - ] - - ] - - for c in code do - AssertCtrlSpaceCompletionListIsEmpty c "this." - AssertAutoCompleteCompletionListIsEmpty c "this." - AssertCtrlSpaceCompletionListIsEmptyNoCoffeeBreak c "this." - AssertAutoCompleteCompletionListIsEmptyNoCoffeeBreak c "this." - [] - member this.``TypeProvider.VisibilityChecksForGeneratedTypes``() = - let extraRefs = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - let check = DoWithAutoCompleteUsingExtraRefs extraRefs None true SourceFileKind.FS BackgroundRequestReason.MemberSelect - - let code = - [ - "type T = GeneratedType.SampleType" - - "let t = T(5)" - "t." - - "T." - - - "type T1() = " - " inherit T(5)" - " member this.Foo() = this." - ] - check code "T." <| - fun ci -> - AssertCompListContains(ci, "PublicField") - - check code "t." <| - fun ci -> - AssertCompListContainsAll(ci, ["PublicM"; "PublicProp"]) - AssertCompListDoesNotContainAny(ci, ["f"; "ProtectedProp"; "PrivateProp"; "ProtectedM"; "PrivateM"]) - - check code "= this." <| - fun ci -> - AssertCompListContainsAll(ci, ["PublicM"; "PublicProp"]) - // The F# compiler never even asks to see protected/private provided members - AssertCompListDoesNotContainAny(ci, ["f"; "ProtectedProp"; "ProtectedM"; "PrivateProp"; "PrivateM"]) - [] member public this.``AdjacentToDot_01``() = testAutoCompleteAdjacentToDot ".." - [] member public this.``AdjacentToDot_02``() = testAutoCompleteAdjacentToDot ".<" - [] member public this.``AdjacentToDot_03``() = testAutoCompleteAdjacentToDot ".>" - [] member public this.``AdjacentToDot_04``() = testAutoCompleteAdjacentToDot ".=" - [] member public this.``AdjacentToDot_05``() = testAutoCompleteAdjacentToDot ".!=" - [] member public this.``AdjacentToDot_06``() = testAutoCompleteAdjacentToDot ".$" - [] member public this.``AdjacentToDot_07``() = testAutoCompleteAdjacentToDot ".[]" - [] member public this.``AdjacentToDot_08``() = testAutoCompleteAdjacentToDot ".[]<-" - [] member public this.``AdjacentToDot_09``() = testAutoCompleteAdjacentToDot ".[,]<-" - [] member public this.``AdjacentToDot_10``() = testAutoCompleteAdjacentToDot ".[,,]<-" - [] member public this.``AdjacentToDot_11``() = testAutoCompleteAdjacentToDot ".[,,,]<-" - [] member public this.``AdjacentToDot_12``() = testAutoCompleteAdjacentToDot ".[,,,]" - [] member public this.``AdjacentToDot_13``() = testAutoCompleteAdjacentToDot ".[,,]" - [] member public this.``AdjacentToDot_14``() = testAutoCompleteAdjacentToDot ".[,]" - [] member public this.``AdjacentToDot_15``() = testAutoCompleteAdjacentToDot ".[..]" - [] member public this.``AdjacentToDot_16``() = testAutoCompleteAdjacentToDot ".[..,..]" - [] member public this.``AdjacentToDot_17``() = testAutoCompleteAdjacentToDot ".[..,..,..]" - [] member public this.``AdjacentToDot_18``() = testAutoCompleteAdjacentToDot ".[..,..,..,..]" - [] member public this.``AdjacentToDot_19``() = testAutoCompleteAdjacentToDot ".()" - [] member public this.``AdjacentToDot_20``() = testAutoCompleteAdjacentToDot ".()<-" - [] member public this.``AdjacentToDot_02_Negative``() = testAutoCompleteAdjacentToDotNegative ".<" - [] member public this.``AdjacentToDot_03_Negative``() = testAutoCompleteAdjacentToDotNegative ".>" - [] member public this.``AdjacentToDot_04_Negative``() = testAutoCompleteAdjacentToDotNegative ".=" - [] member public this.``AdjacentToDot_05_Negative``() = testAutoCompleteAdjacentToDotNegative ".!=" - [] member public this.``AdjacentToDot_06_Negative``() = testAutoCompleteAdjacentToDotNegative ".$" - [] member public this.``AdjacentToDot_07_Negative``() = testAutoCompleteAdjacentToDotNegative ".[]" - [] member public this.``AdjacentToDot_08_Negative``() = testAutoCompleteAdjacentToDotNegative ".[]<-" - [] member public this.``AdjacentToDot_09_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,]<-" - [] member public this.``AdjacentToDot_10_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,]<-" - [] member public this.``AdjacentToDot_11_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,,]<-" - [] member public this.``AdjacentToDot_12_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,,]" - [] member public this.``AdjacentToDot_13_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,]" - [] member public this.``AdjacentToDot_14_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,]" - [] member public this.``AdjacentToDot_15_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..]" - [] member public this.``AdjacentToDot_16_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..,..]" - [] member public this.``AdjacentToDot_17_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..,..,..]" - [] member public this.``AdjacentToDot_18_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..,..,..,..]" - [] member public this.``AdjacentToDot_19_Negative``() = testAutoCompleteAdjacentToDotNegative ".()" - [] member public this.``AdjacentToDot_20_Negative``() = testAutoCompleteAdjacentToDotNegative ".()<-" - [] member public this.``AdjacentToDot_21_Negative``() = testAutoCompleteAdjacentToDotNegative ".+." - - [] - member public this.``LambdaOverloads.Completion``() = - let prologue = "open System.Linq" - let cases = - [ - "[\"\"].Sum(fun x -> (*$*)x.Len )" - "[\"\"].Select(fun x -> (*$*)x.Len )" - "[\"\"].Select(fun x i -> (*$*)x.Len )" - "[\"\"].GroupBy(fun x -> (*$*)x.Len )" - "[\"\"].Join([\"\"], (fun x -> (*$*)x.Len), (fun x -> x.Len), (fun x y -> x.Len+ y.Len))" - "[\"\"].Join([\"\"], (fun x -> x.Len), (fun x -> (*$*)x.Len), (fun x y -> x.Len+ y.Len))" - "[\"\"].Join([\"\"], (fun x -> x.Len), (fun x -> x.Len), (fun x y -> (*$*)x.Len + y.Len))" - "[\"\"].Join([\"\"], (fun x -> x.Len), (fun x -> x.Len), (fun y x -> y.Len + (*$*)x.Len))" - "[\"\"].Where(fun x -> (*$*)x.Len )" - "[\"\"].Where(fun x -> (*$*)x.Len % 3 )" - "[\"\"].Where(fun x -> (*$*)x.Len % 3 = 0)" - "[\"\"].AsQueryable().Select(fun x -> (*$*)x.Len )" - "[\"\"].AsQueryable().Select(fun x i -> (*$*)x.Len )" - "[\"\"].AsQueryable().Where(fun x -> (*$*)x.Len )" - ] - - for case in cases do - let code = [prologue; case] - AssertCtrlSpaceCompleteContains code "(*$*)x.Len" ["Length"] [] - - [] - member public this.``Query.CompletionInJoinOn``() = - let code = - [ - "query {" - " for a in [1] do" - " join b in [2] on (a.)" - " select (a + b)" - "}" - ] - AssertCtrlSpaceCompleteContains code "(a." ["GetHashCode"; "CompareTo"] [] - - - - [] - member public this.``TupledArgsInLambda.Completion.Bug312557_1``() = - let code = - [ - "[(1,2);(1,2);(1,2)]" - "|> Seq.iter (fun (xxx,yyy) -> printfn \"%d\" (*MARKER*)" - " printfn \"%d\" 1)" - ] - AssertCtrlSpaceCompleteContains code "(*MARKER*)" ["xxx"; "yyy"] [] - [] - member public this.``TupledArgsInLambda.Completion.Bug312557_2``() = - let code = - [ - "(1,2) |> (fun (aaa,bbb) ->" - " printfn \"hi\"" - " printfn \"%d%d\" b a" - " printfn \"%d%d\" a b ) " - ] - AssertCtrlSpaceCompleteContains code "\" b" ["aaa"; "bbb"] [] - AssertCtrlSpaceCompleteContains code "\" a" ["aaa"; "bbb"] [] - AssertCtrlSpaceCompleteContains code "b a" ["aaa"; "bbb"] [] - AssertCtrlSpaceCompleteContains code "a b" ["aaa"; "bbb"] [] - [] - member this.``AutoCompletion.OnTypeConstraintError``() = - let code = - [ - "type Foo = Foo" - " with" - " member _.Bar = 1" - " member _.PublicMethodForIntellisense() = 2" - " member internal _.InternalMethod() = 3" - " member private _.PrivateProperty = 4" - "" - "let u: Unit =" - " [ Foo ]" - " |> List.map (fun abcd -> abcd.)" - ] - AssertCtrlSpaceCompleteContains code "abcd." ["Bar"; "Equals"; "GetHashCode"; "GetType"; "InternalMethod"; "PublicMethodForIntellisense"; "ToString"] [] - [] - member public this.``RangeOperator.IncorrectUsage``() = - AssertCtrlSpaceCompletionListIsEmpty [".."] ".." - AssertCtrlSpaceCompletionListIsEmpty ["..."] "..." - [] - member public this.``Inherit.CompletionInConstructorArguments1``() = - let code = - [ - "type A(a : int) = class end" - "type B() = inherit A(a)" - ] - AssertCtrlSpaceCompleteContains code "inherit A(a" ["abs"] [] - [] - member public this.``Inherit.CompletionInConstructorArguments2``() = - let code = - [ - "type A(a : int) = class end" - "type B() = inherit A(System.String.)" - ] - AssertCtrlSpaceCompleteContains code "System.String." ["Empty"] ["Array"; "Collections"] - [] - member public this.``ObjectInitializer.CompletionForProperties``() = - let typeDef1 = - [ - "type A() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - - let typeDef2 = - [ - "type A<'a>() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>((**))"]) "A<_>((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>(S = 1)"]) "A<_>(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>(S = 1)"]) "A<_>(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>(S = 1,)"]) "A<_>(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - - let typeDef3 = - [ - "module M =" - " type A() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A(S = 1)"]) "A(S = 1" [] ["NonSettableProperty"; "SettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["new M.A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["new M.A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["new M.A(S = 1)"]) "A(S = 1" [] ["NonSettableProperty"; "SettableProperty"] // neg test - - let typeDef4 = - [ - "module M =" - " type A<'a, 'b>() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>((**))"]) "A<_, _>((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>(S = 1)"]) "A<_, _>(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>(S = 1)"]) "A<_, _>(S = 1" [] ["NonSettableProperty"; "SettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>(S = 1,)"]) "A<_, _>(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - [] - member public this.``ObjectInitializer.CompletionForSettableExtensionProperties``() = - let typeDef = - [ - "type A() = member this.SetXYZ(v: int) = ()" - "module Ext = type A with member this.XYZ with set(v) = this.SetXYZ(v)" - - ] - AssertCtrlSpaceCompleteContains (typeDef @ ["open Ext"; "A((**))"]) "A((**)" ["XYZ"] [] // positive - AssertCtrlSpaceCompleteContains (typeDef @ ["A((**))"]) "A((**)" [] ["XYZ"] // negative - - [] - member public this.``ObjectInitializer.CompletionForNamedParameters``() = - let typeDef1 = - [ - "type A = " - " static member Run(xyz: int, zyx: string) = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run()"]) ".Run(" ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(x = 1)"]) ".Run(x" ["xyz"] [] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(x = 1,)"]) ".Run(x = 1," ["xyz"; "zyx"] [] - - let typeDef2 = - [ - "type A = " - " static member Run<'T>(xyz: 'T, zyx: string) = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run()"]) ".Run(" ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(x = 1)"]) ".Run(x" ["xyz"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(x = 1,)"]) ".Run(x = 1," ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>()"]) ".Run<_>(" ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(x = 1)"]) ".Run<_>(x" ["xyz"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(x = 1,)"]) ".Run<_>(x = 1," ["xyz"; "zyx"] [] - [] - member public this.``ObjectInitializer.CompletionForSettablePropertiesInReturnValue``() = - let typeDef1 = - [ - "type A0() = member val Settable0 = 1 with get,set" - "type A() = " - " member val Settable = 1 with get,set" - " member val NonSettable = 1" - " static member Run(): A0 = Unchecked.defaultof<_>" - " static member Run(a: string): A = Unchecked.defaultof<_>" - ] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run()"]) ".Run(" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(S = 1)"]) ".Run(S" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(S = 1,)"]) ".Run(S = 1," ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(Settable = 1,)"]) ".Run(Settable = 1," ["Settable0"] ["NonSettable"] - - let typeDef2 = - [ - "type A0() = member val Settable0 = 1 with get,set" - "type A() = " - " member val Settable = 1 with get,set" - " member val NonSettable = 1" - " static member Run<'T>(): A0 = Unchecked.defaultof<_>" - " static member Run(a: int): A = Unchecked.defaultof<_>" - ] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run()"]) ".Run(" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(S = 1)"]) ".Run(S" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(S = 1,)"]) ".Run(S = 1," ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(Settable = 1,)"]) ".Run(Settable = 1," ["Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>()"]) ".Run<_>(" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(S = 1)"]) ".Run<_>(S" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(S = 1,)"]) ".Run<_>(S = 1," ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(Settable = 1,)"]) ".Run<_>(Settable = 1," ["Settable0"] ["NonSettable"] - [] - member public this.``RangeOperator.CorrectUsage``() = - let useCases = - [ - [ - "let _ = [1..]" - ], "1.." - [ - "[" - " 1" - " .." - "]" - ], ".." - ] - for (code, marker) in useCases do - printfn "%A" code - AssertCtrlSpaceCompleteContains code marker ["abs"] [] - printfn "ok" - [] - member public this.``Array.Length.InForRange``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let a = [|1;2;3|] -for i in 0..a."] - "0..a." - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``ProtectedMembers.BaseClass`` () = - let sourceCode = - [ - "type T() = " - " inherit exn()" - " member this.Run(x : exn) = x." - ] - AssertCtrlSpaceCompleteContains sourceCode "x." ["Message"; "HResult"] [] - [] - member public this.``ProtectedMembers.SelfOrDerivedClass`` () = - let sources = - [ - [ - "type T() = " - " inherit exn()" - " member this.Run(x : T) = x." - ] - [ - "type T() = " - " inherit exn()" - " member this.Run(x : Z) = x." - "and Z() =" - " inherit T()" - ] - ] - for src in sources do - AssertCtrlSpaceCompleteContains src "x." ["Message"; "HResult"] [] - [] - member public this.``Records.DotCompletion.ConstructingRecords1``() = - let prologue = "type OuterRec = {XX : int; YY : string}" - - let useCases = - [ - "let _ = (* MARKER*) {X", "(* MARKER*) {X", ["XX"] - "let _ = {XX = 1; (* MARKER*)O", "(* MARKER*)O", ["OuterRec"] - "let _ = {XX = 1; (* MARKER*)OuterRec.", "(* MARKER*)OuterRec.", ["XX"; "YY"] - ] - () - for (code, marker, should) in useCases do - let code = [prologue; code] - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.DotCompletion.ConstructingRecords2``() = - let prologue = - [ - "module Mod = " - " type Rec = {XX : int; YY : string}" - ] - let useCases = - [ - "let _ = (* MARKER*){X }", "(* MARKER*){X", [], ["XX"] - "let _ = {(* MARKER*)Mod. = 1; O", "(* MARKER*)Mod.", ["XX"; "YY"], ["System"] - "let _ = {(* MARKER*)Mod.Rec. ", "(* MARKER*)Mod.Rec.", ["XX"; "YY"], ["System"] - "let _ = (* MARKER*){Mod.XX = 1; }", "(* MARKER*){Mod.XX = 1; ", ["Mod"], ["XX"; "abs"] - ] - - for (code, marker, should, shouldnot) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker should shouldnot - [] - member public this.``Records.CopyOnUpdate``() = - let prologue = - [ - "module SomeOtherPath =" - " type r = { a: int; b : int }" - ] - - let useCases = - [ - "let f1 x = { x with SomeOtherPath. = 3 }", "SomeOtherPath." - "let f2 x = { x with SomeOtherPath.r. = 3 }", "SomeOtherPath.r." - "let f3 (x : SomeOtherPath.r) = { x with }", "x with " - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker ["a"; "b"] ["abs"] - [] - member public this.``Records.CopyOnUpdate.NoFieldsCompletionBeforeWith``() = - let code = - [ - "type T = {AAA : int}" - "let r = {AAA = 5}" - "let b = {r with }" - ] - AssertCtrlSpaceCompleteContains code "{r " [] ["AAA"] - [] - member public this.``Records.Constructors1``() = - let prologue = - [ - "type X =" - " val field1: int" - " val field2: string" - ] - - let useCases = - [ - " new() = { f}", "{ f" - " new() = { field1; }", "field1; " - " new() = { field1 = 5; }", "= 5; " - " new() = { field1 = 5; f }", "5; f" - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker ["field1"; "field2"] ["abs"] - [] - member public this.``Records.Constructors2.UnderscoresInNames``() = - let prologue = - [ - "type X =" - " val _field1: int" - " val _field2: string" - ] - - let useCases = - [ - " new() = { _}", "{ _" - " new() = { _field1; }", "_field1; " - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker ["_field1"; "_field2"] ["abs"] - [] - member public this.``Records.NestedRecordPatterns``() = - let code = ["[1..({contents = 5}).]"] - AssertCtrlSpaceCompleteContains code "5})." ["Value"; "contents"] ["CompareTo"] - [] - member public this.``Records.Separators1``() = - let useCases = - [ - [ - "type X = { AAA : int; BBB : string}" - "let r = {AAA = 5 ; }" - ], "AAA = 5 " - [ - "type X = { AAA : int; BBB : string}" - "let r = {AAA = 5 ; }" - "let b = {r with AAA = 5 ; }" - ], "with AAA = 5 " - ] - - for (code, marker) in useCases do - printfn "checking separators" - printfn "%A" code - AssertCtrlSpaceCompleteContains code marker ["abs"] ["AAA"; "BBB"] - [] - member public this.``Records.Separators2``() = - let useCases = - [ - "Offside rule", [ - "type X = { AAA : int; BBB : string}" - "let r =" - " {" - " AAA = 5" - "(*MARKER*) " - " }" - ], "(*MARKER*)", ["AAA"; "BBB"] - - "Semicolumn", [ - "type X = { AAA : int; BBB : string}" - "let r =" - " {" - " AAA = 5;" - "(*MARKER*) " - " }" - ], "(*MARKER*) ", ["AAA"; "BBB"] - "Semicolumn2", [ - "type X = { AAA : int; BBB : string; CCC : int}" - "let r =" - " {" - " AAA = 5; (*M*)" - " CCC = 5" - " }" - ], "(*M*)", ["AAA"; "BBB"; "CCC"] - ] - - for (caption, code, marker, should) in useCases do - printfn "%s" caption - printfn "%A" code - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.Inherits``() = - let prologue = - [ - "type A = class end" - "type B = " - " inherit A" - " val f1: int" - " val f2: int" - ] - - let useCases = - [ - [" new() = { inherit A(); }"], "inherit A(); ", ["f1"; "f2"] - [ - " new() = { inherit A()" - " (*M*)" - " }"], "(*M*)", ["f1"; "f2"] - ] - for (code, marker, should) in useCases do - let code = prologue @ code - printfn "running:" - printfn "%s" (String.concat "\r\n" code) - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.MissingBindings``() = - let prologue = - [ - "type R = {AAA : int; BBB : bool}" - ] - let useCases = - [ - ["let _ = {A = 1; _; }"], "; _;", ["R"] // ["AAA"; "BBB"] <- this check should be used after fixing 279738 - ["let _ = {A = 1; _=; }"], " _=;", ["R"] // ["AAA"; "BBB"] <- this check should be used after fixing 279738 - ["let _ = {A = 1; R. }"], "1; R.", ["AAA"; "BBB"] - ["let _ = {A = 1; _; R. }"], "_; R.", ["AAA"; "BBB"] - ] - - for (code, marker, should) in useCases do - let code = prologue @ code - printfn "running:" - printfn "%s" (String.concat "\r\n" code) - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.WRONG.ErrorsInFirstBinding``() = - // errors in the first binding are critical now - let prologue = - [ - "type X =" - " val field1: int" - " val field2: string" - ] - - let useCases = - [ - " new() = { field1 =; }", "=; " - " new() = { field1 =; f}", "=; f" - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker [] ["field1"; "field2"] - - [] - member public this.``Records.InferByFieldsInPriorMethodArguments``() = - - let prologue = - [ - "type T() =" - " new (left: float32, top: float32) = T()" - " new (left: float32, top: float32, width: float32, height: float32) = T()" - "" - "type Rect =" - " { Left: float32" - " Top: float32" - " Width: float32" - " Height: float32 }" - ] - - let useCases = - [ - "let toT(original) = T(original.Left, (* MARKER*)original.)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - "let toT(original) = T(original.Left, original.Height, (* MARKER*)original.)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - "let toT(original) = T(original.Left, original.Height, original.Width, (* MARKER*)original.)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - "let toT(original) = T(original.Left, original.Height, (* MARKER*)original., original.Width)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - ] - for (code, marker, should) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker should [] - - [] - member this.``Completion.DetectInterfaces``() = - let shouldBeInterface = - [ - [ - "type X = interface" - " inherit (*M*)" - ] - [ - "[]" - "type X =" - " inherit (*M*)" - ] - [ - "[]" - "type X = interface" - " inherit (*M*)" - ] - ] - for ifs in shouldBeInterface do - AssertCtrlSpaceCompleteContains ifs "(*M*)" ["seq"] [] - - - [] - member this.``Completion.DetectClasses``() = - - let shouldBeClass = - [ - [ - "type X = class" - " inherit (*M*)" - ] - [ - "[]" - "type X =" - " inherit (*M*)" - ] - [ - "[]" - "type X = class" - " inherit (*M*)" - ] - [ - "[]" - "type X() = " - " inherit (*M*)" - ] - ] - for cls in shouldBeClass do - AssertCtrlSpaceCompleteContains cls "(*M*)" ["obj"] [] - - [] - member this.``Completion.DetectUnknownCompletionContext``() = - let content = - [ - "type X = " - " inherit (*M*)" - ] - - AssertCtrlSpaceCompleteContains content "(*M*)" ["obj"; "seq"] [] - - [] - member this.``Completion.DetectInvalidCompletionContext``() = - let shouldBeInvalid = - [ - [ - "type X =" - " inherit System (*M*)." - ] - [ - "type X =" - " inherit System (*M*).Collections" - ] - - ] - - for invalid in shouldBeInvalid do - AssertCtrlSpaceCompletionListIsEmpty invalid "(*M*)" - - [] - member this.``Completion.LongIdentifiers``() = - // System.Diagnostics.Debugger.Launch() |> ignore - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System. " - ] - "System. " - ["IDisposable"; "Array"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System." - " (*M*)" - ] - "(*M*)" - ["IDisposable"; "Array"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System" - " .(*M*)" - ] - "(*M*)" - ["IDisposable"; "Array"] - [] - - // caret is immediately after marker - AssertCtrlSpaceCompleteContains - [ - "module Mod =" - " let x = 1" - "module Mod2 = " - " let x = 1" - "type X = " - " inherit Mod" - ] - " inherit Mod" - ["Mod"; "Mod2"] - [] - - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit Sys" - ] - "Sys" - ["System"; "obj"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System.Collection" - ] - "System.Col" - ["Collections"; "IDisposable"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System. Collections" - ] - "System. " - ["Collections"; "IDisposable"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System. Collections.ArrayList()" - ] - "System. " - ["Collections"; "IDisposable"] - [] - [] - member public this.``Query.GroupJoin.CompletionInIncorrectJoinRelations``() = - let code = - [ - "let t =" - " query {" - " for x in [1] do" - " groupJoin y in [\"\"] on (x. ?=? y.) into g" - " select 1 }" - ] - AssertCtrlSpaceCompleteContains code "(x." ["CompareTo"] ["abs"] - AssertCtrlSpaceCompleteContains code "? y." ["Chars"; "Length"] ["abs"] - [] - member public this.``Query.Join.CompletionInIncorrectJoinRelations``() = - let code = - [ - "let t =" - " query {" - " for x in [1] do" - " join y in [\"\"] on (x. ?=? y.)" - " select 1 }" - ] - AssertCtrlSpaceCompleteContains code "(x." ["CompareTo"] ["abs"] - AssertCtrlSpaceCompleteContains code "? y." ["Chars"; "Length"] ["abs"] - - [] - member public this.``Query.ForKeywordCanCompleteIntoIdentifier``() = - let code = - [ - "let form = 42" - "let t =" - " query {" - " for" - " }" - ] - AssertCtrlSpaceCompleteContains code "for" ["form"] [] // 'for' is a keyword, but should not prevent completion - [] - member public this.``ObjInstance.InheritedClass.MethodsWithDiffAccessibility``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { derivedField = 0;derivedFieldPrivate = 0 } - -let derived = Derived() -derived.derivedField"] - "derived." - [ "baseField"; "derivedField" ] // should contain - [ "baseFieldPrivate"; "derivedFieldPrivate" ] // should not contain - [] - member public this.``ObjInstance.InheritedClass.MethodsWithDiffAccessibilityWithSameNameMethod``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable baseField : int - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { baseField = 0; derivedField = 0; derivedFieldPrivate = 0 } - -let derived = Derived() -derived.derivedField"] - "derived." - [ "baseField"; "derivedField" ] // should contain - [ "baseFieldPrivate"; "derivedFieldPrivate" ] // should not contain - [] - member public this.``Visibility.InheritedClass.MethodsWithDiffAccessibility``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { derivedField = 0;derivedFieldPrivate = 0 } - member this.Method() = - (*marker*)this.baseField"] - "(*marker*)this." - [ "baseField"; "derivedField"; "derivedFieldPrivate" ] // should contain - [ "baseFieldPrivate" ] // should not contain - [] - member public this.``Visibility.InheritedClass.MethodsWithDiffAccessibilityWithSameNameMethod``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable baseField : int - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { baseField = 0; derivedField = 0; derivedFieldPrivate = 0 } - member this.Method() = - (*marker*)this.baseField"] - "(*marker*)this." - [ "baseField"; "derivedField"; "derivedFieldPrivate" ] // should contain - [ "baseFieldPrivate" ] // should not contain - [] - member public this.``Visibility.InheritedClass.MethodsWithSameNameMethod``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type MyClass = - val foo : int - new (foo) = { foo = foo } - -type MyClass2 = - inherit MyClass - val foo : int - new (foo) = { - inherit MyClass(foo) - foo = foo - } - -let x = new MyClass2(0) -(*marker*)x.foo"] - "(*marker*)x." - [ "foo" ] // should contain - [ ] // should not contain - [] - member public this.``Identifier.Array.AfterassertKeyword``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let x = [1;2;3] " - "assert x." ] - "x." - [ "Head" ] // should contain (from List) - [ "Listeners" ] // should not contain (from System.Diagnostics.Debug) - [] - member public this.``CtrlSpaceCompletion.Bug130670.Case1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ "let i = async.Return(4)" ] - ")" - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "GetType" ] // should not contain (object instance method) - [] - member public this.``CtrlSpaceCompletion.Bug130670.Case2``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ """ - let x = 42 - let r = x + 1 """ ] - "1 " - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "CompareTo" ] // should not contain (instance method on int) [] member public this.``CtrlSpaceCompletion.Bug294974.Case1``() = @@ -1317,992 +332,71 @@ let x = new MyClass2(0) [ "xxx" ] // should contain (completions before dot) [ "IsEmpty" ] // should not contain (completions after dot) - [] - member public this.``CtrlSpaceCompletion.Bug294974.Case2``() = - AssertCtrlSpaceCompleteContains - [ """ - let xxx = [1] - xxx .IsEmpty // Ctrl-J just before the '.' """ ] - "xxx " - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "IsEmpty" ] // should not contain (completions after dot) - - [] - member public this.``ObsoleteProperties.6377_1``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Security.SecurityManager." ] - "SecurityManager." - [ "GetStandardSandbox" ] // should contain - [ "get_SecurityEnabled"; "set_SecurityEnabled" ] // should not contain - - [] - member public this.``ObsoleteProperties.6377_2``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Threading.Thread.CurrentThread." ] - "CurrentThread." - [ "CurrentCulture" ] // should contain: just make sure something shows - [ "get_ApartmentState"; "set_ApartmentState" ] // should not contain - - [] - member public this.``PopupsVersusCtrlSpaceOnDotDot.FirstDot.Popup``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Console..BackgroundColor" ] - "System.Console." - [ "BackgroundColor" ] // should contain (from prior System.Console) - [ "abs" ] // should not contain (top-level autocomplete on empty identifier) - [] - member public this.``PopupsVersusCtrlSpaceOnDotDot.FirstDot.CtrlSpace``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ "System.Console..BackgroundColor" ] - "System.Console." - [ "BackgroundColor" ] // should contain (from prior System.Console) - [ "abs" ] // should not contain (top-level autocomplete on empty identifier) - [] - member public this.``DotCompletionInPatternsPartOfLambda``() = - let content = ["let _ = fun x . -> x + 1"] - AssertCtrlSpaceCompletionListIsEmpty content "x ." - [] - member public this.``DotCompletionInBrokenLambda``() = - let content = ["1 |> id (fun x .> x)"] - AssertCtrlSpaceCompletionListIsEmpty content "x ." - [] - member public this.``DotCompletionInPatterns``() = - let useCases = - [ - ["let (x, y .) = 1, 2"], "y ." - ["let run (o : obj) = match o with | :? int as i . -> 1 | _ -> 0"], "as i ." - ["let (``x.y``, ``y.z`` .) = 1, true"], "z`` ." - ["let ``x`` . = 1"], "x`` ." - ] - for (source, marker) in useCases do - AssertCtrlSpaceCompletionListIsEmpty source marker - [] - member public this.``DotCompletionWithBrokenLambda``() = - let errors = - [ - "1 |> id (fun)" - "1 |> id (fun x > x)" - "1 |> id (fun x > )" - "1 |> id (fun x -> )" - ] - let testcases = - [ - for error in errors do - let source = - [ - "let x = 1" - "x." - ] - yield (error::source), "x.", ["CompareTo"], ["Array"] - yield (source @ [error]), "x.", ["CompareTo"], ["Array"] - ] - for (source, marker, should, shouldnot) in testcases do - printfn "%A" source - AssertCtrlSpaceCompleteContains source marker should shouldnot - [] - member public this.``AfterConstructor.5039_1``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader()." ] - "StringReader()." - [ "ReadBlock" ] // should contain (StringReader) - [ "LastIndexOfAny" ] // should not contain (String) - [] - member public this.``AfterConstructor.5039_1.CoffeeBreak``() = - AssertAutoCompleteContains - [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader()." ] - "StringReader()." - [ "ReadBlock" ] // should contain (StringReader) - [ "LastIndexOfAny" ] // should not contain (String) - [] - member public this.``AfterConstructor.5039_2``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Random()." ] - "Random()." - [ "NextDouble" ] // should contain - [ ] // should not contain - [] - member public this.``AfterConstructor.5039_3``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Collections.Generic.List()." ] - "List()." - [ "BinarySearch" ] // should contain - [ ] // should not contain - [] - member public this.``AfterConstructor.5039_4``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Collections.Generic.List()." ] - "List()." - [ "BinarySearch" ] // should contain - [ ] // should not contain - [] - member public this.``Literal.809979``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let value=uint64." ] - "uint64." - [ ] // should contain - [ "Parse" ] // should not contain - [] - member public this.``NameSpace.AsConstructor``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ "new System.DateTime()" ] - "System.DateTime(" // move to marker - ["System";"Array2D"] - ["DaysInMonth"; "AddDays" ] // should contain top level info, no static or instance DateTime members! - [] - member public this.``DotAfterApplication1``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let g a = new System.Random()" - "(g [])."] - "(g [])." - ["Next"] - [ ] - - [] - member public this.``DotAfterApplication2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let g a = new System.Random()" - "g []."] - "g []." - ["Head"] - [ ] - - [] - member public this.``Quickinfo.809979``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let value=uint64." ] - "uint64." - [ ] // should contain - [ "Parse" ] // should not contain - - /// No intellisense in comments/strings! - [] - member public this.``InString``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ // System.C """ , - marker = "// System.C" ) - [] - member public this.``InComment``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ let s = "System.C" """, - marker = "\"System.C") - - /// Intellisense at the top level (on white space) - [] - member public this.``Identifier.OnWhiteSpace.AtTopLevel``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["(*marker*) "] - "(*marker*) " - ["System"; "Array2D"] - ["Int32"] - - /// Intellisense at the top level (after a partial token). All matches should be shown even if there is a unique match - [] - member public this.``TopLevelIdentifier.AfterPartialToken1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let foobaz = 1" - "(*marker*)fo"] - "(*marker*)fo" - ["System";"Array2D";"foobaz"] - ["Int32"] - - [] - member public this.``TopLevelIdentifier.AfterPartialToken2``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let foobaz = 1" - "(*marker*)fo"] - "(*marker*)" - ["System";"Array2D";"foobaz"] - [] - -(* these issues have not been fixed yet, but when they are, here are some tests - [] - member public this.``AutoComplete.Bug65730``() = - AssertAutoCompleteContains - [ "let f x y = x.Equals(y)" ] - "x." // marker - [ "Equals" ] // should contain - [ ] // should not contain - - [] - member public this.``AutoComplete.Bug65731_A``() = - AssertAutoCompleteContains - [ -@"module SomeOtherPath =" -@" type r = { a: int; b : int }" -@"let f1 x = { x with SomeOtherPath.a = 3 } // a" - ] - "SomeOtherPath." // marker - [ "a" ] // should contain - [ ] // should not contain - - [] - member public this.``AutoComplete.Bug65731_B``() = - AssertAutoCompleteContains - [ -@"module SomeOtherPath =" -@" type r = { a: int; b : int }" -@"let f2 x = { x with SomeOtherPath.r.a = 3 } // a" - ] - "SomeOtherPath.r." // marker - [ "a" ] // should contain - [ ] // should not contain + member this.QueryExpressionFileExamples() = + [ """ + module BasicTest + let x = query { for x in [1;2;3] do (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do (*TYPING*) }""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + if x > 3 then + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + where (x > 3) + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + sortBy x + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + (*TYPING*) + sortBy x """ + """ + module BasicTest + let x = query { for x in [1;2;3] do + let y = x + 1 + (*TYPING*)""" ] - [] - member public this.``AutoComplete.Bug69654_0``() = - let code = [ @" - let q = - let a = 42 - let b = (fun i -> i) 43 - // i shows up in Ctrl-space list here, b does not - ((* *)) // but in the parens, things are correct again - "] - - let solution = CreateSolution(this.VS) - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", code) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToStartOfMarker(file, "//") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "b") - AssertCompListDoesNotContain(completions, "i") - MoveCursorToStartOfMarker(file, "(* *)") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "b") - AssertCompListDoesNotContain(completions, "i") + member this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, variations, knownFailures:list<_>) = - gpatcc.AssertExactly(0,0) - - [] - member public this.``AutoComplete.Bug69654_1``() = - let code = [ - "let s = async {" - " let! xxx = async { return 0 }" - " xxx.CompareTo |> ignore // the dot works" - " xxx |> ignore // no xxx" - " do xxx |> ignore // no xxx" - " return xxx // no xxx" - " }" ] - let solution = CreateSolution(this.VS) - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", code) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - - MoveCursorToEndOfMarker(file, "xx.Comp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "CompareTo") - - MoveCursorToStartOfMarker(file, "xx.Comp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToStartOfMarker(file, "xx |>") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "do xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "return xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - gpatcc.AssertExactly(0,0) - - [] - member public this.``AutoComplete.Bug69654_2``() = - let code = [ - "let s = async {" - " use xxx = null" - " xxx.Dispose() // the dot works" - " xxx |> ignore // no xxx" - " do xxx |> ignore // no xxx" - " return xxx // no xxx" - " }" ] - let solution = CreateSolution(this.VS) - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", code) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - - MoveCursorToEndOfMarker(file, "xx.Disp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "Dispose") - - MoveCursorToStartOfMarker(file, "xx.Disp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToStartOfMarker(file, "xx |>") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "do xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "return xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - gpatcc.AssertExactly(0,0) -*) - - [] - member public this.``List.AfterAddLinqNamespace.Bug3754``() = - let code = - ["open System.Xml.Linq" - "List." ] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Xml"; "System.Xml.Linq"]) - MoveCursorToEndOfMarker(file, "List.") - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, [ "map"; "filter" ] ) - - [] - member public this.``Global``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["global."] - "global." - ["System"; "Microsoft" ] - [] - - [] - member public this.``Duplicates.Bug4103a``() = - let code = - [ - "open Microsoft.FSharp.Quotations" - "Expr." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, "Expr.") - let completions = AutoCompleteAtCursor file - - // Get description for Expr.Var - let (CompletionItem(_, _, _, descrFunc, _)) = completions |> Array.find (fun (CompletionItem(name, _, _, _, _)) -> name = "WhileLoop") - let descr = descrFunc() - // Check whether the description contains the name only once - let occurrences = (" " + descr + " ").Split([| "WhileLoop" |], System.StringSplitOptions.None).Length - 1 - // You'll get two occurrences - one for the signature, and one for the doc - AssertEqualWithMessage(2, occurrences, "The entry for 'Expr.Var' is duplicated.") - - /// Testing autocomplete after a dot directly following method call - [] - member public this.``AfterMethod.Bug2296``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type System.Int32 with" - " member x.Int32Member() = 0" - "\"\".CompareTo(\"a\")." ] - "(\"a\")." - ["Int32Member" ] - [] - - /// Testing autocomplete after a dot directly following overloaded method call - [] - member public this.``AfterMethod.Overloaded.Bug2296``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["type System.Boolean with" - " member x.BooleanMember() = 0" - "\"\".Contains(\"a\")."] - "(\"a\")." - ["BooleanMember"] - [] - - [] - member public this.``BasicGlobalMemberList``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x = 1" - "x."] - "x." - ["CompareTo"; "GetHashCode"] - [] - - [] - member public this.``CharLiteral``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x = \"foo\"" - "let x' = \"bar\"" - "x'."] - "x'." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListOnIdentifierEndingWithTick``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x' = 1" - "x'."] - "x'." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListOnIdentifierContainingTick``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x'y = 1" - "x'y."] - "x'y." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListWithPartialMember1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let x = 1" - "x.CompareT"] - "x.CompareT" - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListWithPartialMember2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x = 1" - "x.CompareT"] - "x." - ["CompareTo";"GetHashCode"] - [] - - /// Wrong intellisense for array - [] - member public this.``DotOff.Parenthesized.Expr``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let x = (strs.[1])."] - "(strs.[1])." - ["Substring";"GetHashCode"] - [] - - /// Wrong intellisense for array - [] - member public this.``DotOff.ArrayIndexerNotation``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test1 = strs.[1]."] - "strs.[1]." - ["Substring";"GetHashCode"] - [] - - /// Wrong intellisense for array - [] - member public this.``DotOff.ArraySliceNotation1``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test2 = strs.[1..]." - "let test3 = strs.[..1]." - "let test4 = strs.[1..1]."] - "trs.[1..]." - ["Length"] - [] - - [] - member public this.``DotOff.ArraySliceNotation2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test2 = strs.[1..]." - "let test3 = strs.[..1]." - "let test4 = strs.[1..1]."] - "strs.[..1]." - ["Length"] - [] - - [] - member public this.``DotOff.ArraySliceNotation3``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test2 = strs.[1..]." - "let test3 = strs.[..1]." - "let test4 = strs.[1..1]."] - "strs.[1..1]." - ["Length"] - [] - - [] - member public this.``DotOff.DictionaryIndexer``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let dict = new System.Collections.Generic.Dictionary()" - "let test5 = dict.[1]."] - "dict.[1]." - ["Length"] - [] - - /// intellisense on DOT - [] - member public this.``EmptyFile.Dot.Bug1115``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = "." , - marker = ".") - - [] - member public this.``Identifier.NonDottedNamespace.Bug1347``() = - this.AssertCtrlSpaceCompletionContains( - ["open System" - "open Microsoft.FSharp.Math" - "let x = Mic" - "let p7 =" - " let sieve limit = " - " let isPrime = Array.create (limit+1) true" - " for n in"], - "let x = Mic", - "Microsoft") - - [] - member public this.``MatchStatement.WhenClause.Bug2519``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["type DU = X of int" - "let timefilter pkt =" - " match pkt with" - " | X(hdr) when (*aaa*)hdr." - " | _ -> ()"] - "(*aaa*)hdr." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``String.BeforeIncompleteModuleDefinition.Bug2385``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let s = \"hello\"." - "module Timer ="] - "\"hello\"." - ["Substring";"GetHashCode"] - [] - - [] - member public this.``Project.FsFileWithBuildAction``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let i = 4" - "let r = i.ToString()" - "let x = File1.bob"] - "i." - ["CompareTo"] - [] - - /// Dotting off a string literal should work. - [] - member public this.``DotOff.String``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["\"x\". (*marker*)" - ""] - "\"x\"." - ["Substring";"GetHashCode"] - [] - - /// FEATURE: Pressing dot (.) after an local variable will produce an Intellisense list of members the user may select. - [] - member public this.``BasicLocalMemberList``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let MyFunction (s:string) = " - " let y=\"dog\"" - " y." - " ()"] - " y." - ["Substring";"GetHashCode"] - [] - - [] - member public this.``LocalMemberList.WithPartialMemberEntry1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let MyFunction (s:string) = " - " let y=\"dog\"" - " y.Substri" - " ()"] - " y.Substri" - ["Substring";"GetHashCode"] - [] - - [] - member public this.``LocalMemberList.WithPartialMemberEntry2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let MyFunction (s:string) = " - " let y=\"dog\"" - " y.Substri" - " ()"] - " y." - ["Substring";"GetHashCode"] - [] - - [] - member public this.``CurriedArguments.Regression1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let f" - ["fffff"] - [] - - [] - member public this.``CurriedArguments.Regression2``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test1 = f" - ["fffff"] - [] - - [] - member public this.``CurriedArguments.Regression3``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test1 = fffff \"a\" gg" - ["ggggg"] - [] - - [] - member public this.``CurriedArguments.Regression4``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test2 = fffff 1 gg" - ["ggggg"] - [] - - [] - member public this.``CurriedArguments.Regression5``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test3 = fffff gg" - ["ggggg"] - [] - - [] - member public this.``CurriedArguments.Regression6``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test3 = fffff ggggg gg" - ["ggggg"] - [] - - // Test whether standard types appear in the completion list under both F# and .NET name - [] - member public this.``StandardTypes.Bug4403``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["open System"; "let x=" ] - "let x=" - ["int8"; "int16"; "int32"; "string"; "SByte"; "Int16"; "Int32"; "String" ] - [ ] - - // Test whether standard types appear in the completion list under both F# and .NET name - [] - member public this.``ValueDeclarationHidden.Bug4405``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "do " - " let a = \"string\"" - " let a = if true then 0 else a."] - "else a." - ["IndexOf"; "Substring"] - [ ] - - [] - member public this.``StringFunctions``() = - let code = - [ - "let y = String." - "let f x = 0" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"String.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length > 0) - for completion in completions do - match completion with - | CompletionItem(_,_,_,_,DeclarationType.Method) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected item %s seen with declaration type %A" name x) - - // FEATURE: Pressing ctrl+space or ctrl+j will give a list of valid completions. - - [] - //Verified at least "Some" is contained in the Ctrl-Space Completion list - member public this.``NonDotCompletion``() = - this.AssertCtrlSpaceCompletionContains( - ["let x = S"], - "x = S", - "Some") - - [] - // This test case checks Pressing ctrl+space on the provided Type instance method shows list of valid completions - member this.``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.CtrlSpaceCompletionContains``() = - this.AssertCtrlSpaceCompletionContains( - fileContents = [""" - let t = new N1.T1() - t.I"""], - marker = "t.I", - expected = "IM1", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - // This test case checks Pressing ctrl+space on the provided Type Event shows list of valid completions - member this.``TypeProvider.EditorHideMethodsAttribute.Event.CtrlSpaceCompletionContains``() = - this.AssertCtrlSpaceCompletionContains( - fileContents = [""" - let t = new N.T() - t.Eve"""], - marker = "t.Eve", - expected = "Event1", - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks Pressing ctrl+space on the provided Type static parameter and verify "int" is in the list just to make sure bad things don't happen and autocomplete window pops up - member this.``TypeProvider.EditorHideMethodsAttribute.Type.CtrlSpaceCompletionContains``() = - this.AssertCtrlSpaceCompletionContains( - fileContents = [""" - type boo = N1.T] - member public this.``Class.Self.Bug1544``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = " - type Foo() = - member this.", - marker = "this.") - - // No completion list at the end of file. - [] - member public this.``Identifier.AfterDefined.Bug1545``() = - this.AutoCompletionListNotEmpty - ["let x = [|\"hello\"|]" - "x."] - "x." - - [] - member public this.``Bug243082.DotAfterNewBreaksCompletion`` () = - this.AutoCompletionListNotEmpty - [ - "module A =" - " type B() = class end" - "let s = 1" - "s." - "let z = new A."] - "s." - - [] - member public this.``Bug243082.DotAfterNewBreaksCompletion2`` () = - this.AutoCompletionListNotEmpty - [ - "let s = 1" - "s." - "new System."] - "s." - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest0``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = si(*Marker*)""" , - marker = "(*Marker*)", - list = ["sin"], - addtlRefAssy=standard40AssemblyRefs ) - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest0b``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = qu(*Marker*)""" , - marker = "(*Marker*)", - list = ["query"], - addtlRefAssy=standard40AssemblyRefs ) - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest1``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in [1;2;3] do sel(*Marker*)""" , - marker = "(*Marker*)", - list = ["select"], - addtlRefAssy=standard40AssemblyRefs ) - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest1b``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in [1;2;3] do (*Marker*)""" , - marker = "(*Marker*)", - list = ["select"], - addtlRefAssy=standard40AssemblyRefs ) - - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest2``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in [1;2;3] do sel(*Marker*) }""" , - marker = "(*Marker*)", - list = ["select"], - addtlRefAssy=standard40AssemblyRefs ) - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest3``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for xxxxxx in [1;2;3] do xxx(*Marker*)""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest3b``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = seq { for xxxxxx in [1;2;3] do xxx(*Marker*)""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest3c``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = async { for xxxxxx in [1;2;3] do xxx(*Marker*)""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - [] - member this.``AsyncExpression.CtrlSpaceSmokeTest3d``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = async { for xxxxxx in [1;2;3] do xxx(*Marker*) }""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - member this.QueryExpressionFileExamples() = - [ """ - module BasicTest - let x = query { for x in [1;2;3] do (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do (*TYPING*) }""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - if x > 3 then - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - where (x > 3) - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - sortBy x - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - (*TYPING*) - sortBy x """ - """ - module BasicTest - let x = query { for x in [1;2;3] do - let y = x + 1 - (*TYPING*)""" ] - - [] - /// This is the case where at (*TYPING*) we first type 1...N-1 characters of the target custom operation and then invoke the completion list, and we check that the completion list contains the custom operation - member this.``QueryExpression.CtrlSpaceSystematic1``() = - let rec strictPrefixes (s:string) = seq { if s.Length > 1 then let s = s.[0..s.Length-2] in yield s; yield! strictPrefixes s} - for customOperation in ["select";"skip";"contains";"groupJoin"] do - printfn " Running systematic tests looking for completion of '%s' at multiple locations" customOperation - for idText in strictPrefixes customOperation do - for i,fileContents in this.QueryExpressionFileExamples() |> List.mapi (fun i x -> (i,x)) do - let fileContents = fileContents.Replace("(*TYPING*)",idText+"(*Marker*)") - try - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = fileContents, - marker = "(*Marker*)", - list = [customOperation], - addtlRefAssy=standard40AssemblyRefs ) - with _ -> - printfn "FAILURE: customOperation = %s, idText = %s, fileContents <<<%s>>>" customOperation idText fileContents - reraise() - - - member this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, variations, knownFailures:list<_>) = - - let knownFailuresDict = set knownFailures - printfn "Building systematic tests, excluding %d known failures" knownFailures.Length - let tests = - [ for (suffixName,suffixText) in suffixes do - for builderName in variations do - for (lineName, line, checks) in lines builderName do - for check in checks do - let expectedToFail = knownFailuresDict.Contains (lineName, suffixName, builderName, check) - if not expectedToFail then yield (lineName, suffixName, suffixText, builderName, line, check, expectedToFail) ] + let knownFailuresDict = set knownFailures + printfn "Building systematic tests, excluding %d known failures" knownFailures.Length + let tests = + [ for (suffixName,suffixText) in suffixes do + for builderName in variations do + for (lineName, line, checks) in lines builderName do + for check in checks do + let expectedToFail = knownFailuresDict.Contains (lineName, suffixName, builderName, check) + if not expectedToFail then yield (lineName, suffixName, suffixText, builderName, line, check, expectedToFail) ] let unexpectedSuccesses = ResizeArray<_>() let successes = ResizeArray<_>() @@ -2353,316 +447,11 @@ let x = new MyClass2(0) if failures.Count <> 0 || unexpectedSuccesses.Count <> 0 then raise <| new Exception("there were unexpected results, see console output for details") - [] - member this.``QueryExpressions.QueryAndSequenceExpressionWithForYieldLoopSystematic``() = - - let prefix = """ -module Test -let aaaaaa = [| "1" |] -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "AL1", "let v = " + b + " { " , [] - "AL2", "let v = " + b + " { for " , [] - "AL3", "let v = " + b + " { for bbbb " , [QI "for bbbb" "val bbbb"] - "AL4", "let v = " + b + " { for bbbb in (*C*)" , [QI "for bbbb" "val bbbb"; AC "(*C*)" "aaaaaa" ] - "AL5", "let v = " + b + " { for bbbb in [ (*C*) " , [QI "for bbbb" "val bbbb"; AC "(*C*)" "aaaaaa" ] - "AL6", "let v = " + b + " { for bbbb in [ aaa(*C*) " , [QI "for bbbb" "val bbbb"; AC "(*C*)" "aaaaaa" ] - "AL7", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; DC "(*D1*)" "Length" ] - "AL8", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; DC "(*D1*)" "Length" ] - "AL9", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do (*C*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; AC "(*C*)" (if b = "query" then "select" else "sin"); DC "(*D1*)" "Length" ] - "AL10", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield (*C*) " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; AC "(*C*)" "aaaaaa"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ] - "AL11", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bb(*C*) " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ] - "AL12", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; DC "(*D1*)" "Length" ; DC "(*D2*)" "Length" ] - "AL13", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) + (*C*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; AC "(*C*)" "aaaaaa"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ; DC "(*D2*)" "Length" ] - "AL14", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) + bb(*C*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ; DC "(*D2*)" "Length" ] - "AL15", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) + bbbb(*D3*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; QI "+ bbbb" "val bbbb"; DC "(*D3*)" "Length" ] ] - - - let knownFailures = - [ - ("AL3", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL3", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL6", "NoClosingBrace,NextDefinition", "query", AutoCompleteExpected ("(*C*)","aaaaaa")) - ("AL6", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL6", "NoClosingBrace,NextDefinition", "seq", AutoCompleteExpected ("(*C*)","aaaaaa")) - ("AL6", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL7", "NoClosingBrace,NextDefinition", "query", DotCompleteExpected ("(*D1*)","Length")) - ("AL7", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("aaaaaa","val aaaaaa")) - ("AL7", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL7", "NoClosingBrace,NextDefinition", "seq", DotCompleteExpected ("(*D1*)","Length")) - ("AL7", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("aaaaaa","val aaaaaa")) - ("AL7", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL10", "ClosingBrace", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "ClosingBrace,NextDefinition", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "Empty", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "Empty", "seq", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextDefinition", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextDefinition", "seq", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextTypeDefinition", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextTypeDefinition", "seq", AutoCompleteExpected ("(*C*)","bbbb")) - ] - - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, ["seq";"query"], knownFailures) - - [] - /// Incrementally enter a seq{ .. while ...} loop and check for availability of intellisense etc. - member this.``SequenceExpressions.SequenceExprWithWhileLoopSystematic``() = - - let prefix = """ -module Test -let abbbbc = [| 1 |] -let aaaaaa = 0 -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "BL1", "let f() = seq { while abb(*C*)" , [AC "(*C*)" "abbbbc"] - "BL2", "let f() = seq { while abbbbc(*D1*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"] - "BL3", "let f() = seq { while abbbbc(*D1*) do (*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; AC "(*C*)" "abbbbc"] - "BL4", "let f() = seq { while abbbbc(*D1*) do abb(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; AC "(*C*)" "abbbbc"] - "BL5", "let f() = seq { while abbbbc(*D1*) do abbbbc(*D2*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; DC "(*D2*)" "Length"; ] - "BL6", "let f() = seq { while abbbbc(*D1*) do abbbbc.[(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7a", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)]" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7b", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- " , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7c", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- 1" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7d", "let f() = seq { while abbbbc(*D1*) do abbbbc.[ (*C*) ] <- 1" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL8", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa]" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; ] - "BL9", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- (*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL10", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- aaa(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] ] - - let knownFailures = - [ - ] - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, [""], knownFailures) - [] - /// Incrementally enter query with a 'join' and check for availability of quick info, auto completion and dot completion - member this.``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnSingleLine``() = - - let prefix = """ -module Test -let abbbbc = [| 1 |] -let aaaaaa = 0 -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "CL1", "let x = query { for bbbb in abbbbc(*D0*) do join " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL2", "let x = query { for bbbb in abbbbc(*D0*) do join cccc " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL2a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL3", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL3a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL4", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbb(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - "CL4a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbb(*C*) )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - "CL5", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL5a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL6", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL6a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL6b", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bb(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "bbbb"] - "CL7", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL7a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL8", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb = " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL8a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb = )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL8b", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb = cc(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "cccc"] - "CL9", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL10", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*))" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL11", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL12", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL13", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bb(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL14", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL15", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL16", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cc(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; AC "(*C*)" "cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL17", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] - "CL18", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*))" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] ] - - let knownFailures = - [ - ] - - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, [""], knownFailures) - [] - /// This is a sanity check that the multiple-line case is much the same as the single-line case - member this.``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnMultipleLine``() = - - let prefix = """ -module Test -let abbbbc = [| 1 |] -let aaaaaa = 0 -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "DL1", """ -let x = query { for bbbb in abbbbc(*D0*) do -join -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "DL2", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL2a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL3", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL3a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL4", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbb(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - - "DL4a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbb(*C*) ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - - "DL5", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - - "DL5a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - - "DL6", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - - "L6a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "L6b", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bb(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "bbbb"] - "DL7", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL7a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL8", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb = -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL8a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb = ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL8b", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb = cc(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "cccc"] - "DL9", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL10", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL11", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL12", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL13", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bb(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL14", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL15", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL16", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cc(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; AC "(*C*)" "cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL17", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] - "DL18", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*)) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] ] - - let knownFailures = - - [ - //("DL2", "NoClosingBrace,NextDefinition", "", QuickInfoExpected ("for bbbb","val bbbb")) - //("DL2", "NoClosingBrace,NextDefinition", "", QuickInfoExpected ("in abbbbc","val abbbbc")) - //("DL2", "NoClosingBrace,NextDefinition", "", DotCompleteExpected ("(*D0*)","Length")) - //("DL2", "NoClosingBrace,NextDefinition", "", QuickInfoExpected ("join","join")) - ] - - - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, [""], knownFailures) - [] - /// This is the case where (*TYPING*) nothing has been typed yet and we invoke the completion list - /// This is a known failure right now for some of the example files above. - member this.``QueryExpression.CtrlSpaceSystematic2``() = - for fileContents in this.QueryExpressionFileExamples() do - - try - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = fileContents, - marker = "(*TYPING*)", - list = customOperations, - addtlRefAssy=standard40AssemblyRefs ) - with _ -> - printfn "FAILURE on systematic test: fileContents = <<<%s>>>" fileContents - reraise() @@ -2675,101 +464,14 @@ let x = query { for bbbb in abbbbc(*D0*) do let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." AssertCompListContainsAll(completions, expected) - [] - member public this.``Parameter.CommonCase.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " do (" ], "do (", [ "aaa1" ]) - [] - member public this.``Parameter.SubsequentLet.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " do (" - "let a = 0" ], "do (", [ "aaa1" ]) - [] - member public this.``Parameter.SubsequentMember.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " member x.Foo(aaa2) = " - " do (" - " member x.Bar = 0" ], "do (", [ "aaa1"; "aaa2" ]) - - [] - member public this.``Parameter.System.DateTime.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " member x.Foo(aaa2) = " - " let dt = new System.DateTime(" ], "Time(", [ "aaa1"; "aaa2" ]) - [] - member public this.``Parameter.DirectAfterDefined.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "if true then" - " let aaa1 = 0" - " (" ], "(", [ "aaa1" ]) - [] - member public this.``NotShowInfo.LetBinding.Bug3602``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = "let s. = \"Hello world\" - ()", - marker = "let s.") - [] - member public this.``NotShowInfo.FunctionParameter.Bug3602``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = "let foo s. = s + \"Hello world\" - ()", - marker = "let foo s.") - - [] - member public this.``NotShowInfo.ClassMemberDeclA.Bug3602``() = - this.TestCompletionNotShowingWhenFastUpdate - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " member (*marker*) this.Prop = 10" - "()" ] - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " member (*marker*) this." - "()" ] - "(*marker*) this." // Another test case for the same thing - this goes through a different code path - [] - member public this.``NotShowInfo.ClassMemberDeclB.Bug3602``() = - this.TestCompletionNotShowingWhenFastUpdate - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " // marker$" // <- trick to move the cursor to the right location before source replacement - "()" ] - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " member this." - "()" ] - "marker$" - [] - member public this.``ComputationExpression.LetBang``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let http(url:string) = " - " async { " - " let rnd = new System.Random()" - " let! rsp = rnd.N" ] - "rsp = rnd." - ["Next"] - [] (* Tests for autocomplete -------------------------------------------------------------- *) @@ -2792,948 +494,75 @@ let x = query { for bbbb in abbbbc(*D0*) do AssertCompListContainsAll(completions, expected) gpatcc.AssertExactly(0,0) - [] - member public this.``Generics.Typeof``() = - this.TestGenericAutoComplete ("let _ = typeof.", [ "Assembly"; "AssemblyQualifiedName"; (* ... *) ]) - [] - member public this.``Generics.NonGenericTypeMembers``() = - this.TestGenericAutoComplete ("let _ = GT2.", [ "R"; "S" ]) - [] - member public this.``Generics.GenericTypeMembers``() = - this.TestGenericAutoComplete ("let _ = GT.", [ "P"; "Q" ]) - //[] // keep disabled unless trying to prove that UnhandledExceptionHandler is working - member public this.EnsureThatUnhandledExceptionsCauseAnAssert() = - // Do something that causes LanguageService to load - AssertAutoCompleteContains - [ - "type FooBuilder() =" - " member x.Return(a) = new System.Random()" - "let foo = FooBuilder()" - "(foo { return 0 })." ] - "})." // marker - [ "Next" ] // should contain - [ "GetEnumerator" ] // should not contain - // kaboom - let t = new System.Threading.Thread(new System.Threading.ThreadStart(fun () -> failwith "foo")) - t.Start() - System.Threading.Thread.Sleep(1000) - - [] - member public this.``GenericType.Self.Bug69673_1.01``() = - AssertCtrlSpaceCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "Base(th" - ["this"] - [] - [] - member public this.``GenericType.Self.Bug69673_1.02``() = - AssertCtrlSpaceCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "o = th" - ["this"] - [] - [] - member public this.``GenericType.Self.Bug69673_1.03``() = - AssertCtrlSpaceCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "do th" - ["this"] - [] - [] - member public this.``GenericType.Self.Bug69673_1.04``() = - AssertAutoCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "do this." - ["Bar"] - [] - - [] - member public this.``GenericType.Self.Bug69673_2.1``() = - AssertAutoCompleteContains - ["type Base(o:obj) = class end" - "type Food() as this =" - " class" - " inherit Base(this) // this" - " do" - " this |> ignore // this (only repros with explicit class/end)" - " end" ] - "Base(th" - ["this"] - [] + + - [] - member public this.``GenericType.Self.Bug69673_2.2``() = - AssertAutoCompleteContains - ["type Base(o:obj) = class end" - "type Food() as this =" - " class" - " inherit Base(this) // this" - " do" - " this |> ignore // this (only repros with explicit class/end)" - " end" ] - " th" - ["this"] - [] - [] - member public this.``UnitMeasure.Bug78932_1``() = - AssertAutoCompleteContains - [ @" - module M1 = - [] type Kg - - module M2 = - let f = 1 // <- type . between M1 and ' >' => works" ] - "M1." // marker - [ "Kg" ] // should contain - [ ] // should not contain - [] - member public this.``UnitMeasure.Bug78932_2``() = - // Note: in this case, pressing '.' does not automatically pop up a completion list in VS, but ctrl-space does get the right list - // This is just like how - // let y = true.>"trueSuffix" // no popup on dot, but ctrl-space brings up list with ToString that is legal completion - // works, the issue is ".>" is seen as an operator and not a dot-for-completion. - AssertAutoCompleteContains - [ @" - module M1 = - [] type Kg - - module M2 = - let f = 1 // <- type . between M1 and '>' => no popup intellisense" ] - "M1." // marker - [ "Kg" ] // should contain - [ ] // should not contain - [] - member public this.``Array.AfterOperator...Bug65732_A``() = - AssertAutoCompleteContains - [ "let r = [1 .. System.Int32.MaxValue]" ] - "System." // marker - [ "Int32" ] // should contain - [ "abs" ] // should not contain (from top level) - [] - member public this.``Array.AfterOperator...Bug65732_B``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue..42]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Array.AfterOperator...Bug65732_B2``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue.. 42]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Array.AfterOperator...Bug65732_B3``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue .. 42]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - - [] - member public this.``Array.AfterOperator...Bug65732_C``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue..]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - - [] - member public this.``Array.AfterOperator...Bug65732_D``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue .. ]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Identifier.FuzzyDefined.Bug67133``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let gDateTime (arr: System.DateTime[]) =" - " arr.[0]." ] - "arr.[0]." - ["AddDays"] - [] - - [] - member public this.``Identifier.FuzzyDefined.Bug67133.Negative``() = - let code = [ "let gDateTime (arr: DateTime[]) =" // Note: no 'open System', so DateTime is unknown - " arr.[0]." ] - let (_, _, file) = this.CreateSingleFileProject(code) - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file, "arr.[0].") - let completions = AutoCompleteAtCursor file - AssertCompListContainsExactly(completions, []) // we don't want any completions on . when has unknown type due to errors - // (In particular, we don't want the "didn't find any completions, so just show top-level entities like 'abs' here" logic to kick in.) - [] - member public this.``Class.Property.Bug69150_A``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = (new ClassType(23)).Value" ] - "))." // marker - [ "Value" ] // should contain - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Class.Property.Bug69150_B``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = ClassType(23).Value" ] - "3)." // marker - [ "Value" ] // should contain - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Class.Property.Bug69150_C``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let f x = new ClassType(x)" - "let z = f(23).Value" ] - "3)." // marker - [ "Value" ] // should contain - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Class.Property.Bug69150_D``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = ClassType(23).Value" ] - "3).V" // marker - [ "Value" ] // should contain - [ "VolatileFieldAttribute" ] // should not contain (from top-level) - [] - member public this.``Class.Property.Bug69150_E``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = ClassType(23) . Value" ] - "3) . " // marker - [ "Value" ] // should contain - [ "VolatileFieldAttribute" ] // should not contain (from top-level) - [] - member public this.``AssignmentToProperty.Bug231283``() = - AssertCtrlSpaceCompleteContains - [""" - type Foo() = - member val Bar = 0 with get,set - - let f = new Foo() - f.Bar <- - let xyz = 42 (*Mark*) - xyz """] - "42 " - [ "AbstractClassAttribute" ] // top-level completions - [ "Bar" ] // not stuff from the lhs of assignment - [] - member public this.``Dot.AfterOperator.Bug69159``() = - AssertAutoCompleteContains - [ "let x1 = [|0..1..10|]." ] - "]." // marker - [ "Length" ] // should contain (array) - [ "abs" ] // should not contain (top-level) - [] - member public this.``Residues1``() = - AssertCtrlSpaceCompleteContains - [ "System . Int32 . M" ] - "M" // marker - [ "MaxValue"; "MinValue" ] // should contain - [ "MailboxProcessor"; "Map" ] // should not contain (top-level) - [] - member public this.``Residues2``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "x . C" ] - "C" // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``Residues3``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "x . " ] - ". " // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``Residues4``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "id(x) . C" ] - "C" // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``CtrlSpaceInWhiteSpace.Bug133112``() = - AssertCtrlSpaceCompleteContains - [ """ - type Foo = - static member A = 1 - static member B = 2 - - printfn "%d %d" Foo.A """ ] - "Foo.A " // marker - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "A"; "B" ] // should not contain (Foo) - [] - member public this.``Residues5``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "id(x) . " ] - ". " // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``CompletionInDifferentEnvs1``() = - AssertCtrlSpaceCompleteContains - ["let f1 num =" - " let rec completeword d =" - " d + d" - "(**)comple"] - "(**)comple" // marker - ["completeword"] // should contain - [""] - [] - member public this.``CompletionInDifferentEnvs2``() = - AssertCtrlSpaceCompleteContains - ["let aaa = 1" - "let aab = 2" - "(aa" - "let aac = 3"] - "(aa" - ["aaa"; "aab"] - ["aac"] - [] - member public this.``CompletionInDifferentEnvs3``() = - AssertCtrlSpaceCompleteContains - ["let mb1 = new MailboxProcessor>(fun inbox -> async { let! msg = inbox.Receive()" - " do "] - "do " - ["msg"] - [] - [] - member public this.``CompletionInDifferentEnvs4``() = - AssertCtrlSpaceCompleteContains - ["async {" - " let! x = i" - " (" - "}"] - "(" - ["x"] - [] - AssertCtrlSpaceCompleteContains - ["let q = " - " let a = 20" - " let b = (fun i -> i) 40" - " (("] - "((" - ["b"] - ["i"] - [] - member public this.``CompletionForAndBang_BaseLine0``() = - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "builder {" - " let! xxx3 = 2" - " return x" - "}"] - " return x" - ["xxx3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine1``() = - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let xxx1 = 1" - "builder {" - " let xxx2 = 1" - " let! xxx3 = 1" - " return (1 + x)" - "}"] - " return (1 + x" - ["xxx1"; "xxx2"; "xxx3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine2``() = - /// Without closing '}' - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let yyy1 = 1" - "builder {" - " let yyy2 = 1" - " let! yyy3 = 1" - " return (1 + y)"] - " return (1 + y" - ["yyy1"; "yyy2"; "yyy3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine3``() = - /// Without closing ')' - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let zzz2 = 1" - " let! zzz3 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz2"; "zzz3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine4``() = - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let! zzz3 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz3"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return0``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "builder {" - " let! xxx3 = 2" - " and! xxx4 = 2" - " return x" - "}"] - " return x" - ["xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return1``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let xxx1 = 1" - "builder {" - " let xxx2 = 1" - " let! xxx3 = 1" - " and! xxx4 = 1" - " return (1 + x)" - "}"] - " return (1 + x" - ["xxx1"; "xxx2"; "xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return2``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let yyy1 = 1" - "builder {" - " let yyy2 = 1" - " let! yyy3 = 1" - " and! yyy4 = 1" - " return (1 + y)"] - " return (1 + y" - ["yyy1"; "yyy2"; "yyy3"; "yyy4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return3``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let zzz2 = 1" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz2"; "zzz3"; "zzz4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return4``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz3"; "zzz4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return0``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "builder {" - " let! xxx3 = 2" - " and! xxx4 = 2" - " return x" - "}"] - " return x" - ["xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return1``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let xxx1 = 1" - "builder {" - " let xxx2 = 1" - " let! xxx3 = 1" - " and! xxx4 = 1" - " return (1 + x)" - "}"] - " return (1 + x" - ["xxx1"; "xxx2"; "xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return2``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let yyy1 = 1" - "builder {" - " let yyy2 = 1" - " let! yyy3 = 1" - " and! yyy4 = 1" - " return (1 + y)"] - " return (1 + y" - ["yyy1"; "yyy2"; "yyy3"; "yyy4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return3``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let zzz2 = 1" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz2"; "zzz3"; "zzz4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return4``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz3"; "zzz4"] - [] (**) - [] - member public this.``Bug229433.AfterMismatchedParensCauseWeirdParseTreeAndExceptionDuringTypecheck``() = - AssertAutoCompleteContains [ """ - type T() = - member this.Bar() = () - member val X = "foo" with get,set - static member Id(x) = x - - [1] - |> Seq.iter (fun x -> - let user = x - ["foo"] - |> List.iter (fun m -> - let xyz = new T() - xyz.X <- null - T.Id((*here*)xyz. // no intellisense here after . - ) - printfn "" - ) """ ] - "(*here*)xyz." - [ "Bar"; "X" ] - [] - - [] - member public this.``Bug130733.LongIdSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let c = C() - c.X <- 42""" ] - "c.X" - [ "XX" ] - [] - - [] - member public this.``Bug130733.LongIdSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let c = C() - c.X <- 42""" ] - "c." - [ "XX" ] - [] - [] - member public this.``Bug130733.ExprDotSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let f(x) = C() - f(0).X <- 42""" ] - ").X" - [ "XX" ] - [] - - [] - member public this.``Bug130733.ExprDotSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let f(x) = C() - f(0).X <- 42""" ] - "(0)." - [ "XX" ] - [] - - - [] - member public this.``Bug130733.Nested.LongIdSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let c = C() - c.CC.X <- 42""" ] - "CC.X" - [ "XX" ] - [] - [] - member public this.``Bug130733.Nested.LongIdSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let c = C() - c.CC.X <- 42""" ] - "c.CC." - [ "XX" ] - [] - - [] - member public this.``Bug130733.Nested.ExprDotSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let f(x) = C() - f(0).CC.X <- 42""" ] - "CC.X" - [ "XX" ] - [] - - [] - member public this.``Bug130733.Nested.ExprDotSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let f(x) = C() - f(0).CC.X <- 42""" ] - "(0).CC." - [ "XX" ] - [] - [] - member public this.``Bug130733.NamedIndexedPropertyGet.Dot``() = - AssertAutoCompleteContains [ """ - let str = "foo" - str.Chars(3).""" ] - ")." - [ "CompareTo" ] // char - [] - [] - member public this.``Bug130733.NamedIndexedPropertyGet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - let str = "foo" - str.Chars(3).Co""" ] - ").Co" - [ "CompareTo" ] // char - [] - [] - member public this.``Bug230533.NamedIndexedPropertySet.CtrlSpace.Case1``() = - AssertCtrlSpaceCompleteContains [ """ - type Foo() = - member x.MutableInstanceIndexer - with get (i) = 0 - and set (i) (v:string) = () - - let h() = new Foo() - (h()).MutableInstanceIndexer(0) <- "foo" """ ] - ")).Muta" - [ "MutableInstanceIndexer" ] - [] - [] - member public this.``Bug230533.NamedIndexedPropertySet.CtrlSpace.Case2``() = - AssertCtrlSpaceCompleteContains [ """ - type Foo() = - member x.MutableInstanceIndexer - with get (i) = 0 - and set (i) (v:string) = () - type Bar() = - member this.ZZZ = new Foo() - - let g() = new Bar() - (g()).ZZZ.MutableInstanceIndexer(0) <- "blah" """ ] - ")).ZZZ.Muta" - [ "MutableInstanceIndexer" ] - [] - [] - member public this.``Bug230533.ExprDotSet.CtrlSpace.Case1``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - type D() = - member this.CC = new C() - let f(x) = D() - f(0).CC. <- 42 """ ] - "0).CC." - [ "XX" ] - [] - [] - member public this.``Bug230533.ExprDotSet.CtrlSpace.Case2``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - type D() = - member this.CC with get() = new C() and set(x) = () - let f(x) = D() - f(0).CC. <- 42 """ ] - "0).CC." - [ "XX" ] - [] - [] - member public this.``Attribute.WhenAttachedToLet.Bug70080``() = - this.AutoCompleteBug70080Helper @" - open System - [] - member public this.``Attribute.WhenAttachedToType.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - open System - [] - member public this.``Attribute.WhenAttachedToLetInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper @" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToTypeInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToNothingInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToModuleInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToModule.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - open System - [] - member public this.``Identifer.InMatchStatement.Bug72595``() = - // in this bug, "match blah with let" caused the lexfilter to go awry, which made things hopeless for the parser, yielding no parse tree and thus no intellisense - AssertAutoCompleteContains - [ @" - type C() = - let someValue = ""abc"" - member _.M() = - let x = 1 - match someValue. with - let x = 1 - match 1 with - | _ -> 2 - - type D() = - member x.P = 1 - - [] - do() - " ] - "someValue." // marker - [ "Chars" ] // should contain - [ ] // should not contain - [] - member public this.``HandleInlineComments1``() = - AssertAutoCompleteContains - [ "let rrr = System (* boo! *) . Int32 . MaxValue" ] - ") ." // marker - [ "Int32"] - [ "abs" ] // should not contain (top-level) - [] - member public this.``HandleInlineComments2``() = - AssertAutoCompleteContains - [ "let rrr = System (* boo! *) . Int32 . MaxValue" ] - "2 ." // marker - [ "MaxValue" ] // should contain - [ "abs" ] // should not contain (top-level) [] member public this.``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case1``() = @@ -3743,209 +572,15 @@ let x = query { for bbbb in abbbbc(*D0*) do [ "Collections" ] // should contain (namespace) [ ] // should not contain - [] - member public this.``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case2``() = - AssertAutoCompleteContains - [ "open Microsoft.FSharp.Collections.Array." ] - "Array." // marker - [ "Parallel" ] // should contain (module) - [ "map" ] // should not contain (let-bound value) - - [] - member public this.``BY_DESIGN.CommonScenarioThatBegsTheQuestion.Bug73940``() = - AssertAutoCompleteContains - [ @" - let r = - [""1""] - |> List.map (fun s -> s. // user previous had e.g. '(fun s -> s)' here, but he erased after 's' to end-of-line and hit '.' e.g. to eventually type '.Substring(5))' - |> List.filter (fun s -> s.Length > 5) // parser recover assumes close paren is here, and type inference goes wacky-useless with such a parse - "] - "s." // marker - [ ] // should contain (ideally would be string) - [ "Chars" ] // should not contain (documenting the undesirable behavior, that this does not show up) - - [] - member public this.``BY_DESIGN.ExplicitlyCloseTheParens.Bug73940``() = - AssertAutoCompleteContains - [ @" - let g lam = - lam true |> printfn ""%b"" - sprintf ""%s"" - let r = - [""1""] - |> List.map (fun s -> s. ) // user types close paren here to avoid paren mismatch - |> g // regardless of whatever is down here now, it won't affect the type of 's' above - "] - "s." // marker - [ "Chars" ] // should contain (string) - [ ] // should not contain - - [] - member public this.``BY_DESIGN.MismatchedParenthesesAreHardToRecoverFromAndHereIsWhy.Bug73940``() = - AssertAutoCompleteContains - [ @" - let g lam = - lam true |> printfn ""%b"" - sprintf ""%s"" - let r = - [""1""] - |> List.map (fun s -> s. // it looks like s is a string here, but it's not! - |> g // parser recovers as though there is a right-paren here - "] - "s." // marker - [ "CompareTo" ] // should contain (bool) - [ "Chars" ] // should not contain (string) - -(* - [] - member public this.``AutoComplete.Bug72596_A``() = - AssertAutoCompleteContains - [ "type ClassType() =" - " let foo = fo" ] // is not 'let rec', foo should not be in scope yet, but showed up in completions - "= fo" // marker - [ ] // should contain - [ "foo" ] // should not contain - - - [] - member public this.``AutoComplete.Bug72596_B``() = - AssertAutoCompleteContains - [ "let f() =" - " let foo = fo" ] // is not 'let rec', foo should not be in scope yet, but showed up in completions - "= fo" // marker - [ ] // should contain - [ "foo" ] // should not contain -*) - - [] - member public this.``Expression.MultiLine.Bug66705``() = - AssertAutoCompleteContains - [ "let x = 4" - "let y = x.GetType()" - " .ToString()" ] // "fluent" interface spanning multiple lines - " ." // marker - [ "ToString" ] // should contain - [ ] // should not contain - - [] - member public this.``Expressions.Computation``() = - AssertAutoCompleteContains - [ - "type FooBuilder() =" - " member x.Return(a) = new System.Random()" - "let foo = FooBuilder()" - "(foo { return 0 })." ] - "})." // marker - [ "Next" ] // should contain - [ "GetEnumerator" ] // should not contain - [] - member public this.``Identifier.DefineByVal.InFsiFile.Bug882304_1``() = - AutoCompleteInInterfaceFileContains - [ - "module BasicTest" - "val z:int = 1" - "z." - ] - "z." // marker - [ ] // should contain - [ "Equals" ] // should not contain - [] - member public this.``NameSpace.InFsiFile.Bug882304_2``() = - AutoCompleteInInterfaceFileContains - [ - "module BasicTest" - "open System." - ] - "System." // marker - [ "Action"; // Delegate - "Activator"; // Class - "Collections"; // Subnamespace - "IConvertible" // Interface - ] // should contain - [ ] // should not contain - [] - member public this.``CLIEvents.DefinedInAssemblies.Bug787438``() = - AssertAutoCompleteContains - [ "let mb = new MailboxProcessor(fun _ -> ())" - "mb." ] - "mb." // marker - [ "Error" ] // should contain - [ "add_Error"; "remove_Error" ] // should not contain - [] - member public this.CLIEventsWithByRefArgs() = - AssertAutoCompleteContains - [ "type MyDelegate = delegate of obj * string byref -> unit" - "type mytype() = [] member this.myEvent = (new DelegateEvent()).Publish" - "let t = mytype()" - "t." ] - "t." // marker - [ "add_myEvent"; "remove_myEvent" ] // should contain - [ "myEvent" ] // should not contain - [] - member public this.``Identifier.AfterParenthesis.Bug835276``() = - AssertAutoCompleteContains - [ "let f ( s : string ) =" - " let x = 10 + s.Length" - " for i in 1..10 do" - " let ok = 10 + s.Length // dot here did work" - " let y = 10 +(s." ] - "+(s." // marker - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``Identifier.AfterParenthesis.Bug6484_1``() = - AssertAutoCompleteContains - [ "for x in 1..10 do" - " printfn \"%s\" (x. " ] - "x." // marker - [ "CompareTo" ] // should contain (a method on the 'int' type) - [ ] // should not contain - [] - member public this.``Identifier.AfterParenthesis.Bug6484_2``() = - AssertAutoCompleteContains - [ "for x = 1 to 10 do" - " printfn \"%s\" (x. " ] - "x." // marker - [ "CompareTo" ] // should contain (a method on the 'int' type) - [ ] // should not contain - [] - member public this.``Type.Indexers.Bug4898_1``() = - AssertAutoCompleteContains - [ - "type Foo(len) =" - " member this.Value = [1 .. len]" - "type Bar =" - " static member ParamProp with get len = new Foo(len)" - "let n = Bar.ParamProp."] - "ar.ParamProp." // marker - [ "ToString" ] // should contain - [ "Value" ] // should not contain - [] - member public this.``Type.Indexers.Bug4898_2``() = - AssertAutoCompleteContains - [ - "type mytype() =" - " let instanceArray2 = [|[| \"A\"; \"B\" |]; [| \"A\"; \"B\" |] |]" - " let instanceArray = [| \"A\"; \"B\" |]" - " member x.InstanceIndexer" - " with get(idx) = instanceArray.[idx]" - " member x.InstanceIndexer2" - " with get(idx1,idx2) = instanceArray2.[idx1].[idx2]" - "let a = mytype()" - "a.InstanceIndexer2."] - - "a.InstanceIndexer2." // marker - [ "ToString" ] // should contain - [ "Chars" ] // should not contain [] member public this.``Expressions.Sequence``() = @@ -3956,171 +591,21 @@ let x = query { for bbbb in abbbbc(*D0*) do [ "GetEnumerator" ] // should contain [ ] // should not contain - [] - member public this.``LambdaExpression.WithoutClosing.Bug1346``() = - AssertAutoCompleteContains - [ - "let p4 = " - " let isPalindrome x = " - " let chars = (string_of_int x).ToCharArray()" - " let len = chars." - " chars " - " |> Array.mapi (fun i c ->" ] - "chars." // marker - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``LambdaExpression.WithoutClosing.Bug1346c``() = - AssertAutoCompleteContains - [ - "let p4 = " - " let isPalindrome x = " - " let chars = (string_of_int x).ToCharArray()" - " let len = chars." - " chars " - " |> Array.mapi (fun i c -> )" ] - "chars." // marker - [ "Length" ] // should contain - [ ] // should not contain - - [] - member public this.``LambdaExpression.WithoutClosing.Bug1346b``() = - AssertAutoCompleteContains - [ - "let p4 = " - " let isPalindrome x = " - " let chars = (string_of_int x).ToCharArray()" - " let len = chars." - " chars " - " |> Array.mapi (fun i c ->" - "let p5 = 1" ] - "chars." // marker - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.If_A``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = if (x)." ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.If_C``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = if (x)." - "let y = 2" ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_A``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x)." ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_B``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x). finally ()" ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_C``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x). with e -> () " ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_D``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x)." - "let y = 2" ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Match_A``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = match (x)." ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Match_C``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = match (x)." - "let y = 2"] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteIfClause.Bug4594``() = - AssertCtrlSpaceCompleteContains - [ "let Bar(xyz) ="; - " let hello = "; - " if x" ] - "if x" // move to marker - ["xyz"] [] // should contain 'xyz' - (* Tests for various uses of ObsoleteAttribute ----------------------------------------- *) (* Members marked with obsolete shouldn't be visible, but we should support *) (* dot completions on them *) // Obsolete and CompilerMessage(IsError=true) should not appear. - [] - member public this.``ObsoleteAndOCamlCompatDontAppear``() = - let code= - [ - "open System" - "type X = " - " static member private Private() = ()" - " []" - " static member Obsolete() = ()" - " []" - " static member CompilerMessageTest() = ()" - "X." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"X.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - for completion in completions do - match completion with - | CompletionItem("Obsolete" as s,_,_,_,_) - //| ("Private" as s,_,_,_) this isn't supported yet - | CompletionItem("CompilerMessageTest" as s,_,_,_,_)-> failwith (sprintf "Unexpected item %s at top level." s) - | _ -> () - - // Test various configurations of nested obsolete modules & types - // (also test whether we show the right intellisense) member public this.AutoCompleteObsoleteTest testLine appendDot should shouldnot = let code = [ "[]" @@ -4164,50 +649,11 @@ let x = query { for bbbb in abbbbc(*D0*) do // When the module isn't empty, we should show completion for the module // (and not type-inference based completion on strings - therefore test for 'Chars') - [] - member public this.``Obsolete.TopLevelModule``() = - this.AutoCompleteObsoleteTest "level <- O" false [ "None" ] [ "ObsoleteTop"; "Chars" ] - [] - member public this.``Obsolete.NestedTypeOrModule``() = - this.AutoCompleteObsoleteTest "level <- Module" true [ "Other" ] [ "ObsoleteM"; "ObsoleteT"; "Chars" ] - [] - member public this.``Obsolete.CompletionOnObsoleteModule.Bug3992``() = - this.AutoCompleteObsoleteTest "level <- Module.ObsoleteM" true [ "A" ] [ "ObsoleteNested"; "Chars" ] - [] - member public this.``Obsolete.DoubleNested``() = - this.AutoCompleteObsoleteTest "level <- Module.ObsoleteM.ObsoleteNested" true [ "C" ] [ "Chars" ] - [] - member public this.``Obsolete.CompletionOnObsoleteType``() = - this.AutoCompleteObsoleteTest "level <- Module.ObsoleteT" true [ "B" ] [ "Chars" ] - /// BUG: Referencing a nonexistent DLL caused an assert. - [] - member public this.``WithNonExistentDll``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - // in the project system, 'AddAssemblyReference' would throw, so just poke this into the .fsproj file - PlaceIntoProjectFileBeforeImport - (project, @" - - - ") - let file = AddFileFromText(project,"File1.fs", - [ - "(*marker*) " - ]) - let file = OpenFile(project,"File1.fs") - - MoveCursorToEndOfMarker(file,"(*marker*) ") - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContainsAll(completions,[ - "System"; // .NET namespaces - "Array2D"]) // Types in the F# library - AssertCompListDoesNotContain(completions,"Int32") // Types in the System namespace member internal this.AutoCompleteDuplicatesTest (marker, shortName, fullName:string) = let code = @@ -4242,67 +688,7 @@ let x = query { for bbbb in abbbbc(*D0*) do // This is some tag in the tooltip that also contains the overload name text if descr.Contains("[Signature:") then occurrences - 1 else occurrences - [] - member public this.``Duplicates.Bug4103b``() = - for args in - [ "Test.", "foo", "foo"; - "Test.", "Pat", "Pat"; - "Test.", "Failed", "exception Failed"; - "Test.", "Del", "type Del"; - "Test.", "Foo", "Test.A.Foo" - "Test.B.", "Bar", "Test.B.Bar" - "TestType.", "Prop", "TestType.Prop" - "TestType.", "Event", "TestType.Event" ] do - this.AutoCompleteDuplicatesTest args - - [] - member public this.``Duplicates.Bug4103c``() = - let code = - [ - "open System.IO" - "open System.IO" - "File." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, "File.") - let completions = AutoCompleteAtCursor file - - // Get description for Expr.Var - let (CompletionItem(_, _, _, descrFunc, _)) = completions |> Array.find (fun (CompletionItem(name, _, _, _, _)) -> name = "Open") - let occurrences = this.CountMethodOccurrences(descrFunc(), "File.Open") - AssertEqualWithMessage(3, occurrences, "Found wrong number of overloads for 'File.Open'.") - [] - member public this.``Duplicates.Bug2094``() = - let code = - [ - "open Microsoft.FSharp.Control" - "let b = MailboxProcessor." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, "MailboxProcessor.") - let completions = AutoCompleteAtCursor file - - // Get description for Expr.Var - let (CompletionItem(_, _, _, descrFunc, _)) = completions |> Array.find (fun (CompletionItem(name, _, _, _, _)) -> name = "Start") - let occurrences = this.CountMethodOccurrences(descrFunc(), "Start") - AssertEqualWithMessage(2, occurrences, sprintf "Found wrong number of overloads for 'MailboxProcessor.Start'. Found %A." completions) - - [] - member public this.``WithinMatchClause.Bug1603``() = - let code = - [ - "let rec f l =" - " match l with" - " | [] ->" - " let xx = System.DateTime.Now" - " let y = xx." - " | x :: xs -> f xs" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"let y = xx.") - let completions = AutoCompleteAtCursor file - // Should contain something - Assert.NotEqual(0,completions.Length) - Assert.True(completions |> Array.exists (fun (CompletionItem(name,_,_,_,_)) -> name.Contains("AddMilliseconds"))) // FEATURE: Saving file N does not cause files 1 to N-1 to re-typecheck (but does cause files N to to [] @@ -4438,470 +824,30 @@ let x = query { for bbbb in abbbbc(*D0*) do Assert.NotEqual(0, completions.Length, "Expected some items in the list after adding a reference.") *) - /// In this bug, a bogus flag caused the rest of flag parsing to be ignored. - [] - member public this.``FlagsAndSettings.Bug1969``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", - [ - "let y = System.Deployment.Application." - "()"]) - let file = OpenFile(project, "File1.fs") - MoveCursorToEndOfMarker(file,"System.Deployment.Application.") - let completions = AutoCompleteAtCursor(file) - // printf "Completions=%A\n" completions - Assert.Equal(0, completions.Length) // Expect none here because reference hasn't been added. - // Add an unknown flag followed by the reference to our assembly. - let deploymentAssembly = sprintf @"%s\Microsoft.NET\Framework\v4.0.30319\System.Deployment.dll" (System.Environment.GetEnvironmentVariable("windir")) - SetOtherFlags(project,"--doo-da -r:" + deploymentAssembly) - let completions = AutoCompleteAtCursor(file) - // Now, make sure the reference added after the erroneous reference is still honored. - Assert.NotEqual(0, completions.Length) - ShowErrors(project) - /// In this bug there was an exception if the user pressed dot after a long identifier - /// that was unknown. - [] - member public this.``OfSystemWindows``() = - let code = ["let y=new System.Windows."] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Windows.Forms"]) - MoveCursorToEndOfMarker(file,"System.Windows.") - let completions = AutoCompleteAtCursor(file) - printfn "Completions=%A" completions - Assert.Equal(3, completions.Length) - /// Tests whether we're correctly showing both type and module when they have the same name - [] - member public this.``ShowSetAsModuleAndType``() = - let code = ["let s = Set"] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"= Set") - let completions = CtrlSpaceCompleteAtCursor(file) - let found = completions |> Array.tryFind (fun (CompletionItem(n, _, _, _, _)) -> n = "Set") - match found with - | Some(CompletionItem(_, _, _, f, _)) -> - let tip = f() - AssertContains(tip, "module Set") - AssertContains(tip, "type Set") - | _ -> - Assert.Fail("'Set' not found in the completion list") - - /// FEATURE: The user may type namespace followed by dot and see a completion list containing members of that namespace. - [] - member public this.``AtNamespaceDot``() = - let code = ["let y=new System.String()"] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.") - let completions = AutoCompleteAtCursor(file) - Assert.True(completions.Length>0) - - /// FEATURE: The user will see appropriate glyphs in the autocompletion list. - [] - member public this.``OfSeveralModuleMembers``() = - let code = - [ - "module Module =" - " let Constant = 5" - " type Class = class" - " end" - " type Record = {AString:string}" - " exception OutOfRange of string" - " type Enum = Red = 0 | White = 1 | Blue = 2" - " type DiscriminatedUnion = A | B | C" - " type AsmType = (# \"!0[]\" #)" - " type TupleType = int * int" - " type FunctionType = unit->unit" - " let (~+) x = -x" - " type Interface =" - " abstract MyMethod : unit->unit" - " type Struct = struct" - " end" - " let Function x = 0" - " let FunctionValue = fun x -> 0" - " let Tuple = (0,2)" - " module Submodule =" - " let a = 0" - " type ValueType = int" - "module AbbreviationModule =" - " type StructAbbreviation = Module.Struct" - " type InterfaceAbbreviation = Module.Interface" - " type DiscriminatedUnionAbbreviation = Module.DiscriminatedUnion" - " type RecordAbbreviation = Module.Record" - " type EnumAbbreviation = Module.Enum" - " type TupleTypeAbbreviation = Module.TupleType" - " type AsmTypeAbbreviation = Module.AsmType" - "let y = AbbreviationModule." - "let y = Module." - "let f x = 0" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file," Module.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - - Assert.True(completions.Length>0) - for completion in completions do - match completion with - | CompletionItem("A",_,_,_,DeclarationType.EnumMember) -> () - | CompletionItem("B",_,_,_,DeclarationType.EnumMember) -> () - | CompletionItem("C",_,_,_,DeclarationType.EnumMember) -> () - | CompletionItem("Function",_,_,_,_) -> () - | CompletionItem("Enum",_,_,_,DeclarationType.Enum) -> () - | CompletionItem("Constant",_,_,_,_) -> () - | CompletionItem("FunctionValue",_,_,_,DeclarationType.Method) -> () - | CompletionItem("OutOfRange",_,_,_,DeclarationType.Exception) -> () - | CompletionItem("OutOfRangeException",_,_,_,DeclarationType.Class) -> () - | CompletionItem("Interface",_,_,_,DeclarationType.Interface) -> () - | CompletionItem("Struct",_,_,_,DeclarationType.ValueType) -> () - | CompletionItem("Tuple",_,_,_,_) -> () - | CompletionItem("Submodule",_,_,_,DeclarationType.Module) -> () - | CompletionItem("Record",_,_,_,DeclarationType.Class) -> () - | CompletionItem("DiscriminatedUnion",_,_,_,DeclarationType.DiscriminatedUnion) -> () - | CompletionItem("AsmType",_,_,_,DeclarationType.Class) -> () - | CompletionItem("FunctionType",_,_,_,DeclarationType.Class) -> () - | CompletionItem("TupleType",_,_,_,DeclarationType.Class) -> () - | CompletionItem("ValueType",_,_,_,DeclarationType.ValueType) -> () - | CompletionItem("Class",_,_,_,DeclarationType.Class) -> () - | CompletionItem("Int32",_,_,_,DeclarationType.Method) -> () - | CompletionItem("TupleTypeAbbreviation",_,_,_,_) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected module member %s seen with declaration type %A" name x) - - MoveCursorToEndOfMarker(file,"AbbreviationModule.") - let completions = time1 AutoCompleteAtCursor file "Time of second autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - for completion in completions do - match completion with - | CompletionItem("Int32",_,_,_,_) - | CompletionItem("Function",_,_,_,_) - | CompletionItem("Enum",_,_,_,_) - | CompletionItem("Constant",_,_,_,_) - | CompletionItem("Function",_,_,_,_) - | CompletionItem("Interface",_,_,_,_) - | CompletionItem("Struct",_,_,_,_) - | CompletionItem("Tuple",_,_,_,_) - | CompletionItem("Record",_,_,_,_) -> () - | CompletionItem("EnumAbbreviation",_,_,_,DeclarationType.Enum) -> () - | CompletionItem("InterfaceAbbreviation",_,_,_,DeclarationType.Interface) -> () - | CompletionItem("StructAbbreviation",_,_,_,DeclarationType.ValueType) -> () - | CompletionItem("DiscriminatedUnion",_,_,_,_) -> () - | CompletionItem("RecordAbbreviation",_,_,_,DeclarationType.Class) -> () - | CompletionItem("DiscriminatedUnionAbbreviation",_,_,_,DeclarationType.DiscriminatedUnion) -> () - | CompletionItem("AsmTypeAbbreviation",_,_,_,DeclarationType.Class) -> () - | CompletionItem("TupleTypeAbbreviation",_,_,_,_) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected union member %s seen with declaration type %A" name x) - - [] - member public this.ListFunctions() = - let code = - [ - "let y = List." - "let f x = 0" - ] - let (_,_, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"List.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - for completion in completions do - match completion with - | CompletionItem("Cons",_,_,_,DeclarationType.Method) -> () - | CompletionItem("Equals",_,_,_,DeclarationType.Method) -> () - | CompletionItem("Empty",_,_,_,DeclarationType.Property) -> () - | CompletionItem("empty",_,_,_,_) -> () - | CompletionItem(_,_,_,_,DeclarationType.Method) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected item %s seen with declaration type %A" name x) - - [] - member public this.``SystemNamespace``() = - let code = - [ - "let y = System." - ] - let (_,_, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - let AssertIsDecl(name,decl,expected) = - if decl<>expected then failwith (sprintf "Expected %A for %s but was %A" expected name decl) - - for completion in completions do - match completion with - | CompletionItem("Action" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Class) - | CompletionItem("CodeDom" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Namespace) - | _ -> () // If there is a compile error that prevents a data tip from resolving then show that data tip. - [] - member public this.``MemberInfoCompileErrorsShowInDataTip``() = - let code = - [ - "type Foo = " - " member x.Bar() = 0" - "let foovalue:Foo = unbox null" - "foovalue.B" // make sure this is different from the line 3! - ] - let (_,_, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"foovalue.B") - - use scope = AutoCompleteMemberDataTipsThrowsScope(this.VS, "Simulated compiler error") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - Assert.True(completions.Length>0) - for completion in completions do - let (CompletionItem(_,_,_,descfunc,_)) = completion - let desc = descfunc() - printfn "MemberInfoCompileErrorsShowInDataTip: desc = <<<%s>>>" desc - AssertContains(desc,"Simulated compiler error") // Bunch of crud in empty list. This test asserts that unwanted things don't exist at the top level. - [] - member public this.``Editor.WithoutContext.Bug986``() = - let code = ["(*mark*)"] - let (_,_, file) = this.CreateSingleFileProject(code) - - MoveCursorToEndOfMarker(file,"(*mark*)") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - for completion in completions do - match completion with - | CompletionItem("IChapteredRowset" as s,_,_,_,_) - | CompletionItem("ICorRuntimeHost" as s,_,_,_,_) -> failwith (sprintf "Unexpected item %s at top level." s) - | _ -> () - [] - member public this.``LetBind.TopLevel.Bug1650``() = - let code =["let x = "] - let (_,_, file) = this.CreateSingleFileProject(code) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"let x = ") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - Assert.True(completions.Length>0) - gpatcc.AssertExactly(0,0) - [] - member public this.``Identifier.Invalid.Bug876b``() = - let code = - [ - "let f (x:System.Windows.Forms.Form) = x." - " for x = 0 to 0 do () done" - ] - let (_,project, file) = this.CreateSingleFileProject(code, references = ["System"; "System.Drawing"; "System.Windows.Forms"]) - - MoveCursorToEndOfMarker(file,"x.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - ShowErrors(project) - Assert.True(completions.Length>0) - [] - member public this.``Identifier.Invalid.Bug876c``() = - let code = - [ - "let f (x:System.Windows.Forms.Form) = x." - " 12" - ] - let (_,_, file) = this.CreateSingleFileProject(code, references = ["System"; "System.Drawing"; "System.Windows.Forms"]) - MoveCursorToEndOfMarker(file,"x.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - Assert.True(completions.Length>0) - [] - member public this.``EnumValue.Bug2449``() = - let code = - [ - "type E = | A = 1 | B = 2" - "let e = E.A" - "e." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"e.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListDoesNotContain(completions, "value__") - [] - member public this.``EnumValue.Bug4044``() = - let code = - [ - "open System.IO" - "let GetFileSize filePath = File.GetAttributes(filePath)." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"filePath).") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListDoesNotContain(completions, "value__") - gpatcc.AssertExactly(0,0) - /// There was a bug (2584) that IntelliSense should treat 'int' as a type instead of treating it as a function - /// However, this is now deprecated behavior. We want the user to use 'System.Int32' and - /// we generally prefer information from name resolution (also see 4405) - [] - member public this.``PrimTypeAndFunc``() = - let code = - [ - "System.Int32. " - "int. " - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.Int32.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListContains(completions,"MinValue") - - MoveCursorToEndOfMarker(file,"int.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListDoesNotContain(completions,"MinValue") - /// This is related to Bug1605--since the file couldn't parse there was no information to provide the autocompletion list. - [] - member public this.``MatchStatement.Clause.AfterLetBinds.Bug1603``() = - let code = - [ - "let rec f l =" - " match l with" - " | [] ->" - " let xx = System.DateTime.Now" - " let y = xx" - " | x :: xs -> f xs." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"xs -> f xs.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - let mutable count = 0 - - let AssertIsDecl(name,decl,expected) = - if decl<>expected then failwith (sprintf "Expected %A for %s but was %A" expected name decl) - - for completion in completions do - match completion with - | CompletionItem("Head" as name,_,_,_,decl) -> - count<-count + 1 - AssertIsDecl(name,decl,DeclarationType.Property) - | CompletionItem("Tail" as name,_,_,_,decl) -> - count<-count + 1 - AssertIsDecl(name,decl,DeclarationType.Property) - | CompletionItem(name,_,_,_,x) -> () - - Assert.Equal(2,count) // This was a bug in which the third level of dotting was ignored. - [] - member public this.``ThirdLevelOfDotting``() = - let code = - [ - "let x = System.Console.Wr" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"Console.Wr") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - let AssertIsDecl(name,decl,expected) = - if decl<>expected then failwith (sprintf "Expected %A for %s but was %A" expected name decl) - - for completion in completions do - match completion with - | CompletionItem("BackgroundColor" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Property) - | CompletionItem("CancelKeyEvent" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Event) - | CompletionItem(name,_,_,_,x) -> () // Test completions in an incomplete computation expression (case 1: for "let") - [] - member public this.``ComputationExpressionLet``() = - let code = - [ - "let http(url:string) = " - " async { " - " let rnd = new System.Random()" - " let rsp = rnd.N" ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"rsp = rnd.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListContainsAll(completions, ["Next"]) - [] - member public this.``BestMatch.Bug4320a``() = - let code = [ " let x = System." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.") - let Match text filterText = CompletionBestMatchAtCursorFor(file, text, filterText) - // (ItemName, isUnique, isPrefix) - // isUnique=true means it will be selected on ctrl-space invocation - // isPrefix=true means it will be selected, instead of just outlined - AssertEqual(Some ("GC", false, true), Match "G" None) - AssertEqual(Some ("GC", false, true), Match "GC" None) - AssertEqual(Some ("GCCollectionMode", true, true), Match "GCC" None) - AssertEqual(Some ("GCCollectionMode", false, false), Match "GCCZ" None) - AssertEqual(Some ("GC", false, true), Match "G" (Some "G")) - AssertEqual(Some ("GC", false, true), Match "GC" (Some "G")) - AssertEqual(Some ("GCCollectionMode", true, true), Match "GCC" (Some "G")) - AssertEqual(Some ("GCCollectionMode", false, false), Match "GCCZ" (Some "G")) - AssertEqual(Some ("GC", false, true), Match "G" (Some "GC")) - AssertEqual(Some ("GC", false, true), Match "GC" (Some "GC")) - AssertEqual(Some ("GCCollectionMode", true, true), Match "GCC" (Some "GC")) - AssertEqual(Some ("GCCollectionMode", false, false), Match "GCCZ" (Some "GC")) - [] - member public this.``BestMatch.Bug4320b``() = - let code = [ " let x = List." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"List.") - let Match text = CompletionBestMatchAtCursorFor(file, text, None) - // (ItemName, isUnique, isPrefix) - // isUnique=true means it will be selected on ctrl-space invocation - // isPrefix=true means it will be selected, instead of just outlined - AssertEqual(Some ("empty", false, true), Match "e") - AssertEqual(Some ("empty", true, true), Match "em") - [] - member public this.``BestMatch.Bug5131``() = - let code = [ "System.Environment." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"Environment.") - let Match text = CompletionBestMatchAtCursorFor(file, text, None) - // (ItemName, isUnique, isPrefix) - // isUnique=true means it will be selected on ctrl-space invocation - // isPrefix=true means it will be selected, instead of just outlined - AssertEqual(Some ("OSVersion", true, true), Match "o") - [] - member public this.``COMPILED.DefineNotPropagatedToIncrementalBuilder``() = - use _guard = this.UsingNewVS() - - let solution = this.CreateSolution() - let projName = "testproject" - let project = CreateProject(solution,projName) - let dir = ProjectDirectory(project) - let file1 = AddFileFromText(project,"File1.fs", - [ - "module File1" - "#if COMPILED" - "let x = 0" - "#else" - "let y = 1" - "#endif" - ]) - let file2 = AddFileFromText(project,"File2.fs", - [ - "module File2" - "File1." - ]) - - let file = OpenFile(project, "File2.fs") - MoveCursorToEndOfMarker(file, "File1.") - let completionItems = - AutoCompleteAtCursor(file) - |> Array.map (fun (CompletionItem(name, _, _, _, _)) -> name) - Assert.Equal(1, completionItems.Length) - Assert.Equal("x", completionItems.[0]) - [] member public this.``VisualStudio.CloseAndReopenSolution``() = use _guard = this.UsingNewVS() @@ -4928,2703 +874,145 @@ let x = query { for bbbb in abbbbc(*D0*) do MoveCursorToEndOfMarker(file,"x.") let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - [] - member this.``BadCompletionAfterQuicklyTyping.Bug72561``() = - let code = [ " " ] - let (_, _, file) = this.CreateSingleFileProject(code) - - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - // In this case, we quickly type "." and then get dot-completions - // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) - MoveCursorToEndOfMarker(file, ".") - // Note: no TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContainsExactly(completions, []) // there are no stale results for an expression at this location, so nothing is returned immediately - // second-chance intellisense will kick in: - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, ["Length"]) - AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) - gpatcc.AssertExactly(0,0) - - [] - member this.``BadCompletionAfterQuicklyTyping.Bug72561.Noteworthy.NowWorks``() = - let code = [ "123 " ] - let (_, _, file) = this.CreateSingleFileProject(code) - - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - // In this case, we quickly type "." and then get dot-completions - // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) - MoveCursorToEndOfMarker(file, ".") - // Note: no TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListIsEmpty(completions) // empty completion list means second-chance intellisense will kick in - // if we wait... - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - // ... we get the expected answer - AssertCompListContainsAll(completions, ["Length"]) - AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) - gpatcc.AssertExactly(0,0) - - [] - member this.``BadCompletionAfterQuicklyTyping.Bug130733.NowWorks``() = - let code = [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader() "] - let (_, _, file) = this.CreateSingleFileProject(code) - - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - // In this case, we quickly type "." and then get dot-completions - // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader(). "] - MoveCursorToEndOfMarker(file, "().") - // Note: no TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, ["ReadBlock"]) // text to the left of the dot did not change, so we use stale (correct) result immediately - // if we wait... - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - // ... we get the expected answer - AssertCompListContainsAll(completions, ["ReadBlock"]) - gpatcc.AssertExactly(0,0) - - -//*********************************************Previous Completion test and helper***** - member private this.VerifyCompListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToStartOfMarker(file, marker) - let completions = AutoCompleteAtCursor(file) - AssertCompListDoesNotContainAny(completions,list) - - member private this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToStartOfMarker(file, marker) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListDoesNotContainAny(completions,list) - - member private this.VerifyCompListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToStartOfMarker(file, marker) - let completions = AutoCompleteAtCursor(file) - AssertCompListContainsAll(completions, list) - - member private this.VerifyCtrlSpaceListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list, ?coffeeBreak:bool, ?addtlRefAssy:string list) = - let coffeeBreak = defaultArg coffeeBreak false - let (solution, project, file) = this.CreateSingleFileProject(fileContents, ?references = addtlRefAssy) - MoveCursorToStartOfMarker(file, marker) - if coffeeBreak then TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContainsAll(completions, list) - - - member private this.VerifyAutoCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToEndOfMarker(file, marker) - let completions = AutoCompleteAtCursor(file) - AssertEqual(0,completions.Length) - - member private this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToEndOfMarker(file, marker) - let completions = CtrlSpaceCompleteAtCursor(file) - AssertEqual(0,completions.Length) - - [] - member this.``Expression.WithoutPreDefinedMethods``() = - this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let x = F(*HERE*)""", - marker = "(*HERE*)", - list = ["FSharpDelegateEvent"; "PrivateMethod"; "PrivateType"]) - - [] - member this.``Expression.WithPreDefinedMethods``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module Module1 = - let private PrivateField = 1 - let private PrivateMethod x = - x+1 - type private PrivateType() = - member this.mem = 1 - let a = (*Marker1*) - - let b = 23 - """, - marker = "(*Marker1*)", - list = ["PrivateField"; "PrivateMethod"; "PrivateType"]) - - // Regression for bug 2116 -- Consider making selected item in completion list case-insensitive - [] - member this.``CaseInsensitive``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - type Test() = - member this.Xyzzy = () - member this.xYzzy = () - member this.xyZzy = () - member this.xyzZy = () - member this.xyzzY = () - - let t = new Test() - t.XYZ(*Marker1*) - """, - marker = "(*Marker1*)", - list = ["Xyzzy"; "xYzzy"; "xyZzy"; "xyzZy"; "xyzzY"]) - - [] - member this.``Attributes.CanSeeOpenNamespaces.Bug268290.Case1``() = - AssertCtrlSpaceCompleteContains - [""" - module Foo - open System - [< - """] - "[<" - ["AttributeUsage"] - [] - - [] - member this.``Selection``() = - AssertCtrlSpaceCompleteContains - [""" - let preSelectedItem = 1 - let r = (*MarkerPreSelectedItem*)pre - """] - "(*MarkerPreSelectedItem*)pre" - ["preSelectedItem"] - [] - - // Regression test for 1653 -- Both the F# exception and the .NET exception representing it are shown in completion lists - [] - member this.``NoDupException.Postive``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - let x = Match(*MarkerException*)""", - marker = "(*MarkerException*)", - list = ["MatchFailureException"]) - - [] - member this.``DotNetException.Negative``() = - this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let x = Match(*MarkerException*)""", - marker = "(*MarkerException*)", - list = ["MatchFailure"]) - - // Regression for bug 921 -- intellisense case-insensitive? - [] - member this.``CaseInsensitive.MapMethod``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - List.MaP(*MarkerCase*) - """, - marker = "(*MarkerCase*)", - list = ["map"]) - - //Regression for bug 69644 69654 Fsharp: no completion for an identifier when 'use'd inside an 'async' block - [] - member this.``InAsyncAndUseBlock``() = - this.VerifyCompListContainAllAtStartOfMarker( - fileContents = """ - open System.Text.RegularExpressions - open System.IO - - let collectLinksAsync (url:string) : Async = - async { do printfn "requesting %s" url - let! html = - async { use reader = new System.IO.StreamReader(new System.IO.FileStream("", FileMode.CreateNew)) - do printfn "reading %s" url - return (*Marker1*)reader.ReadToEnd() } //<---- reader - let links = "a" - return links } - """, - marker = "(*Marker1*)", - list = ["reader"]) - - [] - member this.``WithoutOpenNamespace``() = - AssertCtrlSpaceCompleteContains - [""" - module CodeAccessibility - - let x = S(*Marker*) - """] - "(*Marker*)" - [] // should - ["Single"] // should not - - [] - member this.``PrivateVisible``() = - AssertCtrlSpaceCompleteContains - [""" - module CodeAccessibility - - module Module1 = - - let private fieldPrivate = 1 - - let private MethodPrivate x = - x+1 - - type private TypePrivate() = - member this.mem = 1 - - let a = (*Marker1*) - """] - "(*Marker1*) " - ["fieldPrivate";"MethodPrivate";"TypePrivate"] - [] - - [] - member this.``InternalVisible``() = - AssertCtrlSpaceCompleteContains - [""" - module CodeAccessibility - - module Module1 = - - let internal fieldInternal = 1 - - let internal MethodInternal x = - x+1 - - type internal TypeInternal() = - member this.mem = 1 - - let a = (*Marker1*) """] - "(*Marker1*) " - ["fieldInternal";"MethodInternal";"TypeInternal"] // should - [] // should not - - [] - // Verify that we display the correct list of Unit of Measure (Names) in the autocomplete window. - // This also ensures that no UoM are accidentally added or removed. - member public this.``UnitMeasure.UnitNames``() = - AssertAutoCompleteContains - [ "Microsoft.FSharp.Data.UnitSystems.SI.UnitNames."] - "UnitNames." - [ "ampere"; "becquerel"; "candela"; "coulomb"; "farad"; "gray"; "henry"; "hertz"; - "joule"; "katal"; "kelvin"; "kilogram"; "lumen"; "lux"; "metre"; "mole"; "newton"; - "ohm"; "pascal"; "second"; "siemens"; "sievert"; "tesla"; "volt"; "watt"; "weber";] // should contain; exact match - [ ] // should not contain - - [] - // Verify that we display the correct list of Unit of Measure (Symbols) in the autocomplete window. - // This also ensures that no UoM are accidentally added or removed. - member public this.``UnitMeasure.UnitSymbols``() = - AssertAutoCompleteContains - [ "Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols."] - "UnitSymbols." - [ "A"; "Bq"; "C"; "F"; "Gy"; "H"; "Hz"; "J"; "K"; "N"; "Pa"; "S"; "Sv"; "T"; "V"; - "W"; "Wb"; "cd"; "kat"; "kg"; "lm"; "lx"; "m"; "mol"; "ohm"; "s";] // should contain; exact match - [ ] // should not contain - -(*------------------------------------------IDE Query automation start -------------------------------------------------*) - member private this.AssertAutoCompletionInQuery(fileContent : string list, marker:string,contained:string list) = - let file = createFile fileContent SourceFileKind.FS ["System.Xml.Linq"] None - - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file, marker) - let completions = CompleteAtCursorForReason(file,BackgroundRequestReason.CompleteWord) - AssertCompListContainsAll(completions, contained) - gpatcc.AssertExactly(0,0) - - [] - // Custom operators appear in Intellisense list after entering a valid query operator - // on the previous line and invoking Intellisense manually - // Including in a nested query - member public this.``Query.Auto.InNestedQuery``() = - this.AssertAutoCompletionInQuery( - fileContent =[""" - let tuples = [ (1, 8, 9); (56, 45, 3)] - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - let foo = - query { - for n in numbers do - let maxNumber = query {for x in tuples do ma} - select n }"""], - marker = "do ma", - contained = [ "maxBy"; "maxByNullable"; ]) - - [] - // Custom operators appear in Intellisense list after entering a valid query operator - // on the previous line and invoking Intellisense manually - // Including in a nested query - member public this.``Query.Auto.OffSetFromPreviousLine``() = - this.AssertAutoCompletionInQuery( - fileContent =[""" - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let foo = - query { - for n in numbers do - gro - }"""], - marker = "gro", - contained = [ "groupBy"; "groupJoin"; "groupValBy";]) - - [] - member this.``Namespace.System``() = - this.VerifyDotCompListContainAllAtEndOfMarker( - fileContents = """ - // Test '.' after System - open System - let str = "a string" - // Test '.' after str - let _ = str(*usage*) - """, - marker = "open System", - list = [ "IO"; "Collections" ]) - - [] - member this.``Identifier.String.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - let str = "a string" - // Test '.' after str - let _ = str(*usage*) - """, - marker = "(*usage*)", - list = ["Chars"; "ToString"; "Length"; "GetHashCode"]) - - [] - member this.``Identifier.String.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - let str = "a string" - // Test '.' after str - let _ = str(*usage*) - """, - marker = "(*usage*)", - list = ["Parse"; "op_Addition"; "op_Subtraction"]) - - // Verify add_* methods show up for non-standard events. These are events - // where the associated delegate type does not return "void" - [] - member this.``Event.NonStandard.PrefixMethods``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """System.AppDomain.CurrentDomain(*usage*)""", - marker = "(*usage*)", - list = ["add_AssemblyResolve"; "remove_AssemblyResolve"; "add_ReflectionOnlyAssemblyResolve"; "remove_ReflectionOnlyAssemblyResolve"; "add_ResourceResolve"; "remove_ResourceResolve"; "add_TypeResolve"; "remove_TypeResolve"]) - - // Verify the events do show up. An error is generated when they are used asking the user to use add_* and remove_* instead. - // That is, they are legitimate name resolutions but do not pass type checking. - [] - member this.``Event.NonStandard.VerifyLegitimateNameShowUp``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "System.AppDomain.CurrentDomain(*usage*)", - marker = "(*usage*)", - list = ["AssemblyResolve"; "ReflectionOnlyAssemblyResolve"; "ResourceResolve"; "TypeResolve" ]) - - [] - member this.``Array``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let arr = [| for i in 1..10 -> i |](*Mexparray*)", - marker = "(*Mexparray*)", - list = ["Clone"; "IsFixedSize"]) - - [] - member this.``List``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let lst = [ for i in 1..10 -> i](*Mexplist*)", - marker = "(*Mexplist*)", - list = ["Head"; "Tail"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type T() = - member _.P with get() = new T() - member _.M() = [|1..2|] - let t = new T() - t.P.M()(*marker*) """, - marker = "(*marker*)", - list = ["Clone"]) // should contain method on array (result of M call) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test2``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type T() = - member _.M() = [|1..2|] - - type R = { P : T } - - // dotting through an F# record field - let r = { P = T() } - r.P.M()(*marker*) """, - marker = "(*marker*)", - list = ["Clone"]) // should contain method on array (result of M call) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test3``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.Reflection.InterfaceMapping } - - // Dotting through an F# record field and an IL record field - // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib - let r = { P = Unchecked.defaultof } - r.P(*marker*)""", - marker = "(*marker*)", - list = ["InterfaceMethods"]) - - - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test4``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.Reflection.InterfaceMapping } - - // Dotting through an F# record field and an IL record field - // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib - let f() = { P = Unchecked.defaultof } - f().P(*marker*)""", - marker = "(*marker*)", - list = ["InterfaceMethods"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test5``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.Reflection.InterfaceMapping } - - // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib - let f() = { P = Unchecked.defaultof } - f().P.InterfaceMethods(*marker*)""", - marker = "(*marker*)", - list = ["GetEnumerator"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test6``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.AppDomain } - - // Test dotting through an F# record field and a .NET event - let f() = { P = null } - f().P.UnhandledException(*marker*)""", - marker = "(*marker*)", - list = ["AddHandler"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test7``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.AppDomain } - - // Test dotting through an F# record field and a .NET event - let f() = { P = null } - f().P.UnhandledException.GetType()(*marker*)""", - marker = "(*marker*)", - list = ["Assembly"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test8``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type C() = - static member XXX with get() = 4 and set(x) = () - static member CCC with get() = C() - - C.XXX(*marker*) <- 42""", - marker = "(*marker*)", - list = ["CompareTo"]) - - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test9``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type C() = - static member XXX with get() = 4 and set(x) = () - static member CCC with get() = C() - - C.XXX(*marker*) <- 42""", - marker = "(*marker*)", - list = ["CompareTo"]) - - // This test case checks that autocomplete on the provided Type DOES NOT show System.Object members - [] - member this.``TypeProvider.EditorHideMethodsAttribute.Type.DoesnotContain``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let t = new N.T() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["Equals";"GetHashCode"], - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Type shows only the Event1 elements - member this.``TypeProvider.EditorHideMethodsAttribute.Type.Contains``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = new N.T() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["Event1"], - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Type shows the instance method IM1 - member this.``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.Contains``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = new N1.T1() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["IM1"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - // This test case checks that nested types show up only statically and not on instances - member this.``TypeProvider.TypeContainsNestedType``() = - // should have it here - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type XXX = N1.T1(*Marker*)""", - marker = "(*Marker*)", - list = ["SomeNestedType"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - // should _not_ have it here - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let t = new N1.T1() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["SomeNestedType"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - // This test case checks if autocomplete on the provided Event shows only the AddHandler/RemoveHandler elements - member this.``TypeProvider.EditorHideMethodsAttribute.Event.Contain``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""", - marker = "(*Marker*)", - list = ["AddHandler";"RemoveHandler"], - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Method shows no elements - // You can see this as a "negative case" (to check that the usage of the attribute on a method is harmless) - member this.``TypeProvider.EditorHideMethodsAttribute.Method.Contain``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - let t = N.T.M(*Marker*)()""", - marker = "(*Marker*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Property (the type of which is not synthetic) shows the usual elements... like GetType() - // 1. I think it does not make sense to use this attribute on a synthetic property unless it's type is also synthetic (already covered) - // 2. You can see this as a "negative case" (to check that the usage of the attribute is harmless) - member this.``TypeProvider.EditorHideMethodsAttribute.Property.Contain``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = N.T.StaticProp(*Marker*)""", - marker = "(*Marker*)", - list = ["GetType"; "Equals"], // just a couple of System.Object methods: we expect them to be there! - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - member this.CompListInDiffFileTypes() = - let fileContents = """ - val x:int = 1 - x(*MarkerInsideaSignatureFile*) - """ - let (solution, project, openfile) = this.CreateSingleFileProject(fileContents, fileKind = SourceFileKind.FSI) - - let completions = DotCompletionAtStartOfMarker openfile "(*MarkerInsideaSignatureFile*)" - AssertCompListContainsAll(completions, []) // .fsi will not contain completions for this (it doesn't make sense) - - let fileContents = """ - let i = 1 - i(*MarkerInsideSourceFile*) - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - let completions = DotCompletionAtStartOfMarker file "(*MarkerInsideSourceFile*)" - AssertCompListContainsAll(completions, ["CompareTo"; "Equals"]) - - [] - member this.ConstrainedTypes() = - let fileContents = """ - type Pet() = - member x.Name() = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - member x.dog() = "this is a dog" - let dog = new Dog() - let pet = dog :> Pet - pet(*Mupcast*) - let dctest = pet :?> Dog - dctest(*Mdowncast*) - let f (x : bigint) = x(*Mconstrainedtoint*) - """ - let references = - [ - "System.Numerics" // code uses bigint - ] - let (solution, project, file) = this.CreateSingleFileProject(fileContents, references = references) - let completions = DotCompletionAtStartOfMarker file "(*Mupcast*)" - AssertCompListContainsAll(completions, ["Name"; "Speak"]) - - let completions = DotCompletionAtStartOfMarker file "(*Mdowncast*)" - AssertCompListContainsAll(completions, ["dog"; "Name"]) - - let completions = DotCompletionAtStartOfMarker file "(*Mconstrainedtoint*)" - AssertCompListContainsAll(completions, ["ToString"]) - - [] - member this.``Literal.Float``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let myfloat = (42.0)(*Mconstantfloat*)", - marker = "(*Mconstantfloat*)", - list = ["GetType"; "ToString"]) - - [] - member this.``Literal.String``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """let name = "foo"(*Mconstantstring*)""", - marker = "(*Mconstantstring*)", - list = ["Chars"; "Clone"]) - - [] - member this.``Literal.Int``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let typeint = (10)(*Mint*)", - marker = "(*Mint*)", - list = ["GetType";"ToString"]) - - [] - member this.``Identifier.InLambdaExpression``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let funcLambdaExp = fun (x:int)-> x(*MarkerinLambdaExp*)", - marker = "(*MarkerinLambdaExp*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InClass``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type ClassLetBindIn(x:int) = - let m_field = x(*MarkerLetBindinClass*) """, - marker = "(*MarkerLetBindinClass*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InNestedLetBind``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -let funcNestedLetBinding (x:int) = - let funcNested (x:int) = x(*MarkerNestedLetBind*) - () -", - marker = "(*MarkerNestedLetBind*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InModule``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -module ModuleLetBindIn = - let f (x:int) = x(*MarkerLetBindinModule*) -", - marker = "(*MarkerLetBindinModule*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InMatchStatement``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -let x = 1 -match x(*MarkerMatchStatement*) with - |1 -> 1*1 - |2 -> 2*2 - -", - marker = "(*MarkerMatchStatement*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InMatchClause``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -let rec f l = - match l with - | [] -> - let xx = System.DateTime.Now - let y = xx(*MarkerMatchClause*) - () - | x :: xs -> f xs -", - marker = "(*MarkerMatchClause*)", - list = ["Add";"Date"]) - - [] - member this.``Expression.ListItem``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let a = [1;2;3] - a.[1](*MarkerListItem*) - """, - marker = "(*MarkerListItem*)", - list = ["CompareTo"; "ToString"]) - - [] - member this.``Expression.FunctionParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - f ("1" + "1")(*MarkerParameter*) - """, - marker = "(*MarkerParameter*)", - list = ["CompareTo"; "ToString"]) - - [] - member this.``Expression.Function``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let func(mm) = 100 - func(x + y)(*MarkerFunction*) - """, - marker = "(*MarkerFunction*)", - list = ["CompareTo"; "ToString"]) - - [] - member this.``Expression.RecordPattern``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Rec = - { X : int} - member this.Value = 42 - { X = 1 }(*MarkerRecordPattern*) - """, - marker = "(*MarkerRecordPattern*)", - list = ["Value"; "ToString"]) - - [] - member this.``Expression.2DArray``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let (a2: int[,]) = Array2.zero_create 10 10 - a2.[1,2](*Marker2DArray*) - """, - marker = "(*Marker2DArray*)", - list = ["ToString"]) - - [] - member this.``Expression.LetBind``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - //And in many different contexts where the ??tomic expression??occurs at the end of the expression, e.g. - let x = y in f ("1" + "1")(*MarkerContext1*) - """, - marker = "(*MarkerContext1*)", - list = ["CompareTo";"ToString"]) - - [] - member this.``Expression.WhileLoop``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - while true do - f ("1" + "1")(*MarkerContext3*) - """, - marker = "(*MarkerContext3*)", - list = ["CompareTo";"ToString"]) - - [] - member this.``Expression.List``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """[1;2](*MarkerList*) """, - marker = "(*MarkerList*)", - list = ["Head"; "Item"]) - - [] - member this.``Expression.Nested.InLetBind``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - // Nested expressions - let x = 42 |> ignore; f ("1" + "1")(*MarkerNested1*) - """, - marker = "(*MarkerNested1*)", - list = ["Chars";"Length"]) - - [] - member this.``Expression.Nested.InWhileLoop``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - while true do - ignore (f ("1" + "1")(*MarkerNested2*)) - """, - marker = "(*MarkerNested2*)", - list = ["Chars";"Length"]) - - [] - member this.``Expression.ArrayItem.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - //regression test for bug 1001 - let str1 = Array.init 10 string - str1.[1](*MarkerArrayIndexer*)""", - marker = "(*MarkerArrayIndexer*)", - list = ["Chars";"Split"]) - - [] - member this.``Expression.ArrayItem.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - //regression test for bug 1001 - let str1 = Array.init 10 string - str1.[1](*MarkerArrayIndexer*)""", - marker = "(*MarkerArrayIndexer*)", - list = ["IsReadOnly";"Rank"]) - - [] - member this.``ObjInstance.InheritedClass.MethodsDefInBase``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Pet() = - member x.Name() = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - member x.dog() = "this is a dog" - let dog = new Dog() - dog(*Mderived*)""", - marker = "(*Mderived*)", - list = ["Name"; "dog"]) - - [] - member this.``ObjInstance.AnonymousClass.MethodsDefInInterface``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type IFoo = - abstract DoStuff : unit -> string - abstract DoStuff2 : int * int -> string -> string - // Implement an interface in a class (This is kind of lame if you don't want to actually declare a class) - type Foo() = - interface IFoo with - member this.DoStuff () = "Return a string" - member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z - // instanceOfIFoo is an instance of an anonymous class which implements IFoo - let instanceOfIFoo = { - new IFoo with - member this.DoStuff () = "Implement IFoo" - member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z - }(*Mexpnewtype*)""", - marker = "(*Mexpnewtype*)", - list = ["DoStuff"; "DoStuff2"]) - - [] - member this.``SimpleTypes.SystemTime``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let typestruct = System.DateTime.Now - typestruct(*Mstruct*)""", - marker = "(*Mstruct*)", - list = ["AddDays"; "Date"]) - - [] - member this.``SimpleTypes.Record``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Person = { Name: string; DateOfBirth: System.DateTime } - let typrecord = { Name = "Bill"; DateOfBirth = new System.DateTime(1962,09,02) } - typrecord(*Mrecord*)""", - marker = "(*Mrecord*)", - list = ["DateOfBirth"; "Name"]) - - [] - member this.``SimpleTypes.Enum``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type weekday = - | Monday = 1 - | Tuesday = 2 - | Wednesday = 3 - | Thursday = 4 - | Friday = 5 - let typeenum = weekday.Friday - typeenum(*Menum*)""", - marker = "(*Menum*)", - list = ["GetType"; "ToString"]) - - [] - member this.``SimpleTypes.DisUnion``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Route = int - type Make = string - type Model = string - type Transport = - | Car of Make * Model - | Bicycle - | Bus of Route - let typediscriminatedunion = Car("BMW","360") - typediscriminatedunion(*Mdiscriminatedunion*)""", - marker = "(*Mdiscriminatedunion*)", - list = ["GetType"; "ToString"]) - - [] - member this.``InheritedClass.BaseClassPrivateMethod.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - //define the base class - type Widget() = - let mutable state = 0 - member internal x.MethodInternal() = state - member public x.MethodPublic(n) = state <- state + n - member private x.MethodPrivate() = (state <> 0) - [] - val mutable internal fieldInternal:int - [] - val mutable public fieldPublic:int - [] - val mutable private fieldPrivate:int - //define the divided class which inherent "Widget" - type Divided() = - inherit Widget() - member x.myPrint() = - base(*MUnShowPrivate*) - Console.ReadKey(true)""" , - marker = "(*MUnShowPrivate*)", - list = ["MethodPrivate";"fieldPrivate"]) - - [] - member this.``InheritedClass.BaseClassPublicMethodAndProperty``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - //define the base class - type Widget() = - let mutable state = 0 - member internal x.MethodInternal() = state - member public x.MethodPublic(n) = state <- state + n - member private x.MethodPrivate() = (state <> 0) - [] - val mutable internal fieldInternal:int - [] - val mutable public fieldPublic:int - [] - val mutable private fieldPrivate:int - //define the divided class which inherent "Widget" - type Divided() = - inherit Widget() - member x.myPrint() = - base(*MShowPublic*) - Console.ReadKey(true)""", - marker = "(*MShowPublic*)", - list = ["MethodPublic";"fieldPublic"]) - - [] - member this.``Visibility.InternalNestedClass.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """System.Console(*Marker1*)""", - marker = "(*Marker1*)", - list = ["ControlCDelegateData"]) - - [] - member this.``Visibility.PrivateIdentifierInDiffModule.Negative``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - module Module1 = - let private fieldPrivate = 1 - let private MethodPrivate x = - x+1 - type private TypePrivate()= - member this.mem = 1 - module Module2 = - Module1(*Marker1*) """, - marker = "(*Marker1*)") - - [] - member this.``Visibility.PrivateIdentifierInDiffClass.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - module Module1 = - type Type1()= - [] - val mutable private fieldPrivate:int - member private x.MethodPrivate() = 1 - type Type2()= - let M1= - let type1 = new Type1() - type1(*MarkerOutType*) """, - marker = "(*MarkerOutType*)", - list = ["fieldPrivate";"MethodPrivate"]) - - [] - member this.``Visibility.PrivateFieldInSameClass``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - - module Module1 = - type Type1()= - [] - val mutable private PrivateField:int - static member private PrivateMethod() = 1 - member this.Field1 with get () = this(*MarkerFieldInType*) - member x.MethodTest() = Type1(*MarkerMethodInType*) - let type1 = new Type1() """, - marker = "(*MarkerFieldInType*)", - list = ["PrivateField"]) - - [] - member this.``Visibility.PrivateMethodInSameClass``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - - module Module1 = - type Type1()= - [] - val mutable private PrivateField:int - static member private PrivateMethod() = 1 - member this.Field1 with get () = this(*MarkerFieldInType*) - member x.MethodTest() = Type1(*MarkerMethodInType*) - let type1 = new Type1() """, - marker = "(*MarkerMethodInType*)", - list = ["PrivateMethod"]) - -// [] - member this.``VariableIdentifier.AsParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 """, - marker = "(*Maftervariable1*)", - list = ["Tag"]) - - [] - member this.``VariableIdentifier.InMeasure.DefineInDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog() - namespace MyNamespace2 - module MyModule2 = - let typeFunc<[] 'a> = [1; 2; 3] - let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 - let y = int System.IO(*Maftervariable5*)""", - marker = "(*Maftervariable2*)", - list = []) - - [] - member this.``VariableIdentifier.MethodsInheritFromBase``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog()""", - marker = "(*Maftervariable3*)", - list = ["Name";"Speak"]) - - [] - member this.``VariableIdentifier.AsParameter.DefineInDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog() - namespace MyNamespace2 - module MyModule2 = - let typeFunc = [1; 2; 3] - let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 - let y = int System.IO(*Maftervariable5*)""", - marker = "(*Maftervariable4*)", - list = ["DuType"]) - - [] - member this.``VariableIdentifier.SystemNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog() - namespace MyNamespace2 - module MyModule2 = - let typeFunc = [1; 2; 3] - let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 - let y = int System.IO(*Maftervariable5*)""", - marker = "(*Maftervariable5*)", - list = ["BinaryReader";"Stream";"Directory"]) - - [] - member this.``LongIdent.AsAttribute``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - [] - type TestAttribute() = - member x.print() = "print" """, - marker = "(*Mattribute*)", - list = ["Obsolete"]) - - [] - member this.``ImportStatement.System.ImportDirectly``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System(*Mimportstatement1*) - open IO = System(*Mimportstatement2*)""", - marker = "(*Mimportstatement1*)", - list = ["Collections"]) - - [] - member this.``ImportStatement.System.ImportAsIdentifier``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System(*Mimportstatement1*) - open IO = System(*Mimportstatement2*)""", - marker = "(*Mimportstatement2*)", - list = ["IO"]) - - [] - member this.``LongIdent.PatternMatch.AsVariable.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS - module longident = - type Direction = - | Left = 1 - | Right = 2 - type MoveCursor() = - member this.Direction = Direction.Left - namespace NS2 - module test = - let cursor = new NS.longident.MoveCursor() - match cursor(*Mpatternmatch1*) with - | NS.longident.Direction.Left -> "move left" - | NS(*Mpatternmatch2*) -> "move right" """, - marker = "(*Mpatternmatch1*)", - list = ["Direction";"ToString"]) - - [] - member this.``LongIdent.PatternMatch.AsConstantValue.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS - module longident = - type Direction = - | Left = 1 - | Right = 2 - type MoveCursor() = - member this.Direction = Direction.Left - namespace NS2 - module test = - let cursor = new NS.longident.MoveCursor() - match cursor(*Mpatternmatch1*) with - | NS.longident.Direction.Left -> "move left" - | NS(*Mpatternmatch2*) -> "move right" """, - marker = "(*Mpatternmatch2*)", - list = ["longident"]) - - [] - member this.``LongIdent.PInvoke.AsReturnType``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.IO - open System.Runtime.InteropServices - // Get two temp files, write data into one of them - let tempFile1, tempFile2 = Path.GetTempFileName(), Path.GetTempFileName() - let writer = new StreamWriter (tempFile1) - writer.WriteLine("Some Data") - writer.Close() - // Original signature - //[] - //extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists); - [] - extern System(*Mpinvokereturntype*) CopyFile_Arrays(char[] lpExistingFileName, char[] lpNewFileName, bool bFailIfExists); - let result = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) - printfn "Array %A" result""", - marker = "(*Mpinvokereturntype*)", - list = ["Boolean";"Int32"]) - - [] - member this.``LongIdent.PInvoke.AsAttribute``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.IO - open System.Runtime.InteropServices - - module mymodule = - type SomeAttrib() = - inherit System.Attribute() - type myclass() = - member x.name() = "test case" - module mymodule2 = - [] - extern bool CopyFile_Attrib([] char [] lpExistingFileName, char []lpNewFileName, [] bool & bFailIfExists); - - let result5 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) - printfn "WithAttribute %A" result5""", - marker = "(*Mpinvokeattribute*)", - list = ["SomeAttrib"]) - - [] - member this.``LongIdent.PInvoke.AsParameterType``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.IO - open System.Runtime.InteropServices - [] - extern bool CopyFile_ArraySpaces(char [] lpExistingFileName, char []lpNewFileName, System(*Mpinvokeparametertype*) bFailIfExists); - let result2 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) - printfn "Array Space %A" result2""", - marker = "(*Mpinvokeparametertype*)", - list = ["Boolean";"Int32"]) - - [] - member this.``LongIdent.Record.AsField``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module MyModule = - type person = - { name: string; - dateOfBirth: System.DateTime; } - module MyModule2 = - let x = {MyModule(*Mrecord*) = 32}""", - marker = "(*Mrecord*)", - list = ["person"]) - - [] - member this.``LongIdent.DiscUnion.AsTypeParameter.DefInDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - namespace MyNamespace2 - module MyModule2 = - let foo = MyNamespace1.MyModule(*Mtypeparameter1*) - let f (x:int) = MyNamespace1.MyModule.DuType(*Mtypeparameter2*) - let typeFunc<[] 'a> = 10""", - marker = "(*Mtypeparameter1*)", - list = ["Dog";"DuType"]) - - [] - member this.``LongIdent.AnonymousFunction.AsTypeParameter.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - namespace MyNamespace2 - module MyModule2 = - let foo = MyNamespace1.MyModule(*Mtypeparameter1*) - let f (x:int) = MyNamespace1.MyModule.DuType(*Mtypeparameter2*) - let typeFunc<[] 'a> = 10""", - marker = "(*Mtypeparameter2*)", - list = ["Tag"]) - - [] - member this.``LongIdent.UnitMeasure.AsTypeParameter.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - namespace MyNamespace2 - module MyModule2 = - let foo = MyNamespace1.MyModule(*Mtypeparameter1*) - let f (x:int) = MyNamespace1.MyModule.DuType(*Mtypeparameter2*) - let typeFunc<[] 'a> = 10""", - marker = "(*Mtypeparameter3*)", - list = []) - - [] - member this.``RedefinedIdentifier.DiffScope.InScope.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let identifierBothScope = "" - let functionScope () = - let identifierBothScope = System.DateTime.Now - identifierBothScope(*MarkerShowLastOneWhenInScope*) - identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""", - marker = "(*MarkerShowLastOneWhenInScope*)", - list = ["DayOfWeek"]) - - [] - member this.``RedefinedIdentifier.DiffScope.InScope.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let identifierBothScope = "" - let functionScope () = - let identifierBothScope = System.DateTime.Now - identifierBothScope(*MarkerShowLastOneWhenInScope*) - identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""", - marker = "(*MarkerShowLastOneWhenInScope*)", - list = ["Chars"]) - - [] - member this.``RedefinedIdentifier.DiffScope.OutScope.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let identifierBothScope = "" - let functionScope () = - let identifierBothScope = System.DateTime.Now - identifierBothScope(*MarkerShowLastOneWhenInScope*) - identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""", - marker = "(*MarkerShowLastOneWhenOutscoped*)", - list = ["Chars"]) - - [] - member this.``ObjInstance.ExtensionMethods.WithoutDef.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - let rnd = new System.Random() - rnd(*MWithoutReference*)""", - marker = "(*MWithoutReference*)", - list = ["NextDice";"DiceValue"]) - - [] - member this.``Class.DefInDiffNameSpace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*) - """, - marker = "(*MarkerType*)" , - list = ["TestType"]) - - [] - member this.``Class.DefInDiffNameSpace.WithAttributes.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*) - """, - marker = "(*MarkerType*)", - list = ["ObsoleteType";"CompilerMessageType"]) - - [] - member this.``Method.DefInDiffNameSpace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*) - """, - marker = "(*MarkerMethod*)", - list = ["TestMethod"; "VisibleMethod";"VisibleMethod2"]) - - [] - member this.``Method.DefInDiffNameSpace.WithAttributes.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*)""", - marker = "(*MarkerMethod*)", - list = ["ObsoleteMethod";"CompilerMessageMethod";"HiddenMethod"]) - - [] - member this.``ObjInstance.ExtensionMethods.WithDef.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - - type System.Random with - member this.NextDice() = true - member this.DiceValue = 6 - - let rnd = new System.Random() - rnd(*MWithReference*)""", - marker = "(*MWithReference*)", - list = ["NextDice";"DiceValue"]) - - [] - member this.``Keywords.If``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - if(*MarkerKeywordIf*) true then - () """, - marker ="(*MarkerKeywordIf*)") - - [] - member this.``Keywords.Let``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """let(*MarkerKeywordLet*) a = 1""", - marker = "(*MarkerKeywordLet*)") - - [] - member this.``Keywords.Match``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - match(*MarkerKeywordMatch*) a with - | pattern -> exp""", - marker = "(*MarkerKeywordMatch*)") - - [] - member this.``MacroDirectives.nowarn``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """#nowarn(*MarkerPreProcessNowarn*)""", - marker = "(*MarkerPreProcessNowarn*)") - - [] - member this.``MacroDirectives.define``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """#define(*MarkerPreProcessDefine*)""", - marker = "(*MarkerPreProcessDefine*)") - - [] - member this.``MacroDirectives.PreProcessDefine``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """#define Foo(*MarkerPreProcessDefineConst*)""", - marker = "(*MarkerPreProcessDefineConst*)") - - [] - member this.``Identifier.InClass.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Type2 = - val mutable x(*MarkerValue*) : string""", - marker = "(*MarkerValue*)") - - [] - member this.``Identifier.InDiscUnion.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type DUTag = - |Tag(*MarkerDU*) of int""", - marker = "(*MarkerDU*)") - - [] - member this.``Identifier.InRecord.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """type Rec = { X(*MarkerRec*) : int }""", - marker = "(*MarkerRec*)") - - [] - member this.``Identifier.AsNamespace``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """namespace Namespace1(*MarkerNamespace*)""", - marker = "(*MarkerNamespace*)") - - [] - member this.``Identifier.AsModule``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """module Module1(*MarkerModule*)""", - marker = "(*MarkerModule*)") - - [] - member this.``Identifier.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ abcd(*MarkerUndefinedIdentifier*) """, - marker = "(*MarkerUndefinedIdentifier*)") - - [] - member this.``Identifier.InMatch.UnderScore``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - let x = 1 - match x with - |1 -> 1*2 - |2 -> 2*2 - |_(*MarkerIdentifierIsUnderScore*) -> 0 """, - marker = "(*MarkerIdentifierIsUnderScore*)") - - [] - member this.MemberSelf() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Foo() = - member this(*Mmemberself*)""", - marker = "(*Mmemberself*)") - - [] - member this.``Expression.InComment``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - //open System - //open IO = System(*Mcomment*)""", - marker = "(*Mcomment*)") - - [] - member this.``Expression.InString``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """let x = "System.Console(*Minstring*)" """, - marker = "(*Minstring*)") - - // Regression test for 1067 -- Completion lists don't work after generic arguments - for generic functions and for static members of generic types - [] - member this.``Regression1067.InstanceOfGenericType``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type GT<'a> = - static member P = 12 - static member Q = 13 - - let _ = GT(*Marker1*) - type gt_int = GT - gt_int(*Marker2*) - - type D = - class - end - - let x = typeof(*Marker3*) - let y = typeof - y(*Marker4*) - """, - marker = "(*Marker2*)", - list = ["P"; "Q"]) - - [] - member this.``Regression1067.ClassUsingGenericTypeAsAttribute``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type GT<'a> = - static member P = 12 - static member Q = 13 - - let _ = GT(*Marker1*) - type gt_int = GT - gt_int(*Marker2*) - - type D = - class - end - - let x = typeof(*Marker3*) - let y = typeof - y(*Marker4*) - """, - marker = "(*Marker4*)", - list = ["Assembly"; "FullName"; "GUID"]) - - [] - member this.NoInfiniteLoopInProperties() = - let fileContents = """ - open System.Windows.Forms - - let tn = new TreeNode("") - - tn.Nodes(*Marker1*)""" - let (solution, project, file) = this.CreateSingleFileProject(fileContents, references = ["System.Windows.Forms"]) - - let completions = DotCompletionAtStartOfMarker file "(*Marker1*)" - AssertCompListDoesNotContainAny(completions, ["Nodes"]) - - // Regression for bug 3225 -- Invalid intellisense when inside of a quotation - [] - member this.``Regression3225.Identifier.InQuotation``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let _ = <@ let x = "foo" - x(*Marker*) @>""", - marker = "(*Marker*)", - list = ["Chars"; "Length"]) - - // Regression for bug 1911 -- No completion list of expr in match statement - [] - member this.``Regression1911.Expression.InMatchStatement``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Thingy = { A : bool; B : int } - - let test = match (List.head [{A = true; B = 0}; {A = false; B = 1}])(*Marker*)""", - marker = "(*Marker*)", - list = ["A"; "B"]) - - - // Bug 3627 - Completion lists should be filtered in many contexts - // This blocks six testcases and is slated for Dev11, so these will be disabled for some time. - [] - member this.AfterTypeParameter() = - let fileContents = """ - type Type1 = Tag of string(*MarkerDUTypeParam*) - - let f x:int -> string(*MarkerParamFunction*) - - let Type2<'a(*MarkerGenericParam*)> = 1 - - let type1 = typeof - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - //Completion list Not comes up after DUType parameter - let completions = DotCompletionAtStartOfMarker file "(*MarkerDUTypeParam*)" - AssertCompListIsEmpty(completions) - - //Completion list Not comes up after function parameter - let completions = DotCompletionAtStartOfMarker file "(*MarkerParamFunction*)" - AssertCompListIsEmpty(completions) - - //Completion list Not comes up after generic parameter - let completions = DotCompletionAtStartOfMarker file "(*MarkerGenericParam*)" - AssertCompListIsEmpty(completions) - - //Completion list Not comes up after parameter in typeof - let completions = DotCompletionAtStartOfMarker file "(*MarkerParamTypeof*)" - AssertCompListIsEmpty(completions) - - [] - member this.``Identifier.AsClassName.InInitial``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type f1(*MarkerType*) = - val field: int""", - marker = "(*MarkerType*)") - - [] - member this.``Identifier.AsFunctionName.InInitial``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """let f2(*MarkerFunctionIdentifier*) x = x+1 """, - marker = "(*MarkerFunctionIdentifier*)") - - [] - member this.``Identifier.AsParameter.InInitial``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ let f3 x(*MarkerParam*) = x+1""", - marker = "(*MarkerParam*)") - - [] - member this.``Identifier.AsFunctionName.UsingFunKeyword``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """fun f4(*MarkerFunctionDeclaration*) x -> x+1""", - marker = "(*MarkerFunctionDeclaration*)") - - [] - member public this.``Identifier.EqualityConstraint.Bug65730``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """let g3<'a when 'a : equality> (x:'a) = x(*Marker*)""", - marker = "(*Marker*)", - list = ["Equals"; "GetHashCode"]) // equality constraint should make these show up - - [] - member this.``Identifier.InFunctionMatch``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - let f5 = function - | 1(*MarkerFunctionMatch*) -> printfn "1" - | 2 -> printfn "2" """, - marker = "(*MarkerFunctionMatch*)") - - [] - member this.``Identifier.This``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Type1 = - member this(*MarkerMemberThis*).Foo () = 3""", - marker = "(*MarkerMemberThis*)") - - [] - member this.``Identifier.AsProperty``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Type2 = - member this.Foo(*MarkerMemberThisProperty*) = 1""", - marker = "(*MarkerMemberThisProperty*)") - - [] - member this.``ExpressionPropertyAssignment.Bug217051``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Foo() = - member val Prop = 0 with get, set - - Foo()(*Marker*) <- 4 """, - marker = "(*Marker*)", - list = ["Prop"]) - - [] - member this.``ExpressionProperty.Bug234687``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.Reflection - let x = obj() - let a = x.GetType().Assembly(*Marker*) - """, - marker = "(*Marker*)", - list = ["CodeBase"]) // expect instance properties of Assembly, not static Assembly methods - - [] - member this.NotShowAttribute() = - let fileContents = """ - open System - - [] - type testclass() = - member x.Name() = "test" - - [] - type testattribute() = - member x.Empty = 0 - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - //Completion List----where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mattribute1*)" - AssertCompListIsEmpty(completions) - - //Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mattribute2*)" - AssertCompListIsEmpty(completions) - - [] - member this.NotShowPInvokeSignature() = - let fileContents = """ - //open System - //open IO = System(*Mcomment*) - - #if RELEASE - System.Console(*Mdisablecode*) - #endif - - let x = "System.Console(*Minstring*)" - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - - // description="Completion List----where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mreturntype*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mfunctionname*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mparametertype*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mparameter*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mparameterlist*)" - AssertCompListIsEmpty(completions) - - [] - member this.``Basic.Completion.UnfinishedLet``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let g(x) = x+1 - - let f() = - let r = g(4)(*Marker*) """, - marker = "(*Marker*)", - list = ["CompareTo"]) - - [] - member this.``ShortFormSeqExpr.Bug229610``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module test - open System.Text.RegularExpressions - - let limit = 50 - let linkPat = "href=\s*\"[^\"h]*(http://[^&\"]*)\"" - let getLinks (txt:string) = [ for m in Regex.Matches(txt,linkPat) -> m.Groups.Item(1)(*Marker*) ] """, - marker = "(*Marker*)", - list = ["Value"]) + Assert.True(completions.Length>0) - //Regression test for bug 69159 Fsharp: dot completion is mission for an array - [] - member this.``Array.InitialUsing..``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """let x1 = [| 0.0 .. 0.1 .. 10.0 |](*Marker*)""", - marker = "(*Marker*)", - list = ["Length";"Clone";"ToString"]) - - //Regression test for bug 65740 Fsharp: dot completion is mission after a '#' statement - [] - member this.``Identifier.In#Statement``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - # 29 "original-test-file.fs" - let argv = System.Environment.GetCommandLineArgs() - - let SetCulture() = - if argv(*Marker*)Length > 2 && argv.[1] = "--culture" then - let cultureString = argv.[2] - """, - marker = "(*Marker*)", - list = ["Length";"Clone";"ToString"]) - - //This test is about CompletionList which should be moved to completionList, it's too special to refactor. - //Regression test for bug 72595 typing quickly yields wrong intellisense - [] - member this.``BadCompletionAfterQuicklyTyping``() = + [] + member this.``BadCompletionAfterQuicklyTyping.Bug72561``() = let code = [ " " ] let (_, _, file) = this.CreateSingleFileProject(code) - + TakeCoffeeBreak(this.VS) - + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) // In this case, we quickly type "." and then get dot-completions - // For "level <- Module" this shows completions from the "Module" (e.g. "Module.Other") // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) MoveCursorToEndOfMarker(file, ".") + // Note: no TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + AssertCompListContainsExactly(completions, []) // there are no stale results for an expression at this location, so nothing is returned immediately + // second-chance intellisense will kick in: TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file AssertCompListContainsAll(completions, ["Length"]) AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) + gpatcc.AssertExactly(0,0) - [] - member this.``SelfParameter.InDoKeywordScope``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type foo() as this = - do - this(*Marker*)""", - marker = "(*Marker*)", - list = ["ToString"]) - - [] - member this.``SelfParameter.InDoKeywordScope.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - type foo() as this = - do - this(*Marker*)""", - marker = "(*Marker*)", - list = ["Value";"Contents"]) - - [] - member this.``ReOpenNameSpace.StaticProperties``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - // Static properties & events - namespace A - type TestType = - static member Prop = 0 - static member Event = (new Event()).Publish - namespace B - open A - open A - TestType(*Marker1*)""", - marker = "(*Marker1*)", - list = ["Prop";"Event"]) - - [] - member this.``ReOpenNameSpace.EnumTypes``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - // F# declared enum types: - namespace A - module Test = - type A = | Foo = 0 - - namespace B - open A - open A - Test.A(*Marker2*) - """, - marker = "(*Marker2*)", - list = ["Foo"]) - - [] - member this.``ReOpenNameSpace.SystemLibrary``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open System.IO - open System.IO - - File(*Marker3*) - """, - marker = "(*Marker3*)", - list = ["Open"]) - - [] - member this.``ReOpenNameSpace.FsharpQuotation``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open Microsoft.FSharp.Quotations - open Microsoft.FSharp.Quotations - Expr(*Marker4*) - """, - marker = "(*Marker4*)", - list = ["Value"]) - - [] - member this.``ReOpenNameSpace.MailboxProcessor``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open Microsoft.FSharp.Control - open Microsoft.FSharp.Control - let counter = - MailboxProcessor(*Marker6*)""", - marker = "(*Marker6*)", - list = ["Start"]) - - [] - member this.``ReopenNamespace.Module``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace A - module Test = - let foo n = n + 1 - namespace B - open A - open A - Test(*Marker7*)""", - marker = "(*Marker7*)", - list = ["foo"]) - - [] - member this.``Expression.InLetScope``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - - let p4 = - let isPalindrome x = - let chars = (string_of_int x).ToCharArray() - let len = chars(*Marker1*) - chars - |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""", - marker = "(*Marker1*)", - list = ["IsFixedSize";"Initialize"]) - - [] - member this.``Expression.InFunScope.FirstParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let p4 = - let isPalindrome x = - let chars = (string_of_int x).ToCharArray() - let len = chars(*Marker1*) - chars - |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""", - marker = "(*Marker2*)", - list = ["CompareTo"]) - - [] - member this.``Expression.InFunScope.SecParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - - let p4 = - let isPalindrome x = - let chars = (string_of_int x).ToCharArray() - let len = chars(*Marker1*) - chars - |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""", - marker = "(*Marker3*)", - list = ["GetType";"ToString"]) - - [] - member this.``Expression.InMatchWhenClause``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - type DU = X of int - - let timefilter pkt = - match pkt with - | X(hdr) when hdr(*MarkerMatch*) -> () - | _ -> () - """, - marker = "(*MarkerMatch*)", - list = ["CompareTo";"ToString"]) - - //Regression test for bug 3223 in PS: No intellisense at point - [] - member this.``Identifier.InActivePattern.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3223 No intellisense at point - - open Microsoft.FSharp.Quotations.Patterns - open Microsoft.FSharp.Quotations.DerivedPatterns - - let test1 = <@ 1 + 1 @> - let _ = - match test1 with - | Call(None, methInfo, args) -> - if methInfo(*Marker*) - """, - marker = "(*Marker*)", - list = ["Attributes";"CallingConvention";"ContainsGenericParameters"]) - - [] - member this.``Identifier.InActivePattern.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3223 No intellisense at point - - open Microsoft.FSharp.Quotations.Patterns - open Microsoft.FSharp.Quotations.DerivedPatterns - - let test1 = <@ 1 + 1 @> - let _ = - match test1 with - | Call(None, methInfo, args) -> - if methInfo(*Marker*) - """, - marker = "(*Marker*)", - list = ["Head";"ToInt"]) - - //Regression test of bug 2296:No completion lists on the direct results of a method call - [] - member this.``Regression2296.DirectResultsOfMethodCall``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - """, - marker = "(*Marker1*)", - list = ["Attributes";"CallingConvention";"IsFamily"]) - - [] - member this.``Regression2296.DirectResultsOfMethodCall.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - """, - marker = "(*Marker1*)", - list = ["value__"]) - - [] - member this.``Regression2296.Identifier.String.Reflection01``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - - let programType = executingAssembly.GetType("Program") - - let message = programType.GetMethod("foo")(*Marker1*) - - let x = "" - let _ = x.Contains("a")(*Marker2*)""", - marker = "(*Marker2*)", - list = ["CompareTo";"GetType";"ToString"]) - - [] - member this.``Regression2296.Identifier.String.Reflection01.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - - let programType = executingAssembly.GetType("Program") - - let message = programType.GetMethod("foo")(*Marker1*) - - let x = "" - let _ = x.Contains("a")(*Marker2*)""", - marker = "(*Marker2*)", - list = ["value__"]) - - [] - member this.``Regression2296.Identifier.String.Reflection02``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - - let programType = executingAssembly.GetType("Program") - - let message = programType.GetMethod("foo")(*Marker1*) - - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*)""", - marker = "(*Marker3*)", - list = ["CompareTo";"GetType";"ToString"]) - - [] - member this.``Regression2296.Identifier.String.Reflection02.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*)""", - marker = "(*Marker3*)", - list = ["value__"]) - - [] - member this.``Regression2296.System.StaticMethod.Reflection``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*) - - open System.IO - - let GetFileSize filePath = File.GetAttributes(filePath)(*Marker4*)""", - marker = "(*Marker4*)", - list = ["CompareTo";"GetType";"ToString"]) - - [] - member this.``Regression2296.System.StaticMethod.Reflection.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*) - - open System.IO - - let GetFileSize filePath = File.GetAttributes(filePath)(*Marker4*)""", - marker = "(*Marker4*)", - list = ["value__"]) - - [] - member this.``Seq.NearTheEndOfFile``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open Microsoft.FSharp.Math + [] + member this.``BadCompletionAfterQuicklyTyping.Bug72561.Noteworthy.NowWorks``() = + let code = [ "123 " ] + let (_, _, file) = this.CreateSingleFileProject(code) + + TakeCoffeeBreak(this.VS) + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) + // In this case, we quickly type "." and then get dot-completions + // This simulates the case when the user quickly types "dot" after the file has been TCed before. + ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) + MoveCursorToEndOfMarker(file, ".") + // Note: no TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + AssertCompListIsEmpty(completions) // empty completion list means second-chance intellisense will kick in + // if we wait... + TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + // ... we get the expected answer + AssertCompListContainsAll(completions, ["Length"]) + AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) + gpatcc.AssertExactly(0,0) - let trianglenumbers = Seq.init_infinite (fun i -> let i = BigInt(i) in i * (i+1I) / 2I) + [] + member this.``BadCompletionAfterQuicklyTyping.Bug130733.NowWorks``() = + let code = [ "let someCall(x) = null" + "let xe = someCall(System.IO.StringReader() "] + let (_, _, file) = this.CreateSingleFileProject(code) + + TakeCoffeeBreak(this.VS) + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) + // In this case, we quickly type "." and then get dot-completions + // This simulates the case when the user quickly types "dot" after the file has been TCed before. + ReplaceFileInMemoryWithoutCoffeeBreak file [ "let someCall(x) = null" + "let xe = someCall(System.IO.StringReader(). "] + MoveCursorToEndOfMarker(file, "().") + // Note: no TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + AssertCompListContainsAll(completions, ["ReadBlock"]) // text to the left of the dot did not change, so we use stale (correct) result immediately + // if we wait... + TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + // ... we get the expected answer + AssertCompListContainsAll(completions, ["ReadBlock"]) + gpatcc.AssertExactly(0,0) - (trianglenumbers |> Seq(*MarkerNearTheEnd*))""", - marker = "(*MarkerNearTheEnd*)", - list = ["cache";"find"]) - //Regression test of bug 3879: intellisense glitch for computation expression - [] - member this.``ComputationExpression.WithClosingBrace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3879: intellisense glitch for computation expression - // intellisense does not work in computation expression without the closing brace - type System.Net.WebRequest with - - member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) - member x.GetResponseAsync() = x.AsyncGetResponse() - - let http(url:string) = - async {let req = System.Net.WebRequest.Create("http://www.yahoo.com") - let! rsp = req(*Marker*)} """, - marker = "(*Marker*)", - list = ["AsyncGetResponse";"GetResponseAsync";"ToString"]) - - [] - member this.``ComputationExpression.WithoutClosingBrace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3879: intellisense glitch for computation expression - // intellisense does not work in computation expression without the closing brace - type System.Net.WebRequest with +//*********************************************Previous Completion test and helper***** + member private this.VerifyCompListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToStartOfMarker(file, marker) + let completions = AutoCompleteAtCursor(file) + AssertCompListDoesNotContainAny(completions,list) - member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) - member x.GetResponseAsync() = x.AsyncGetResponse() + member private this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToStartOfMarker(file, marker) + let completions = CtrlSpaceCompleteAtCursor file + AssertCompListDoesNotContainAny(completions,list) - let http(url:string) = - async { let req = System.Net.WebRequest.Create("http://www.yahoo.com") - let! rsp = req(*Marker*) """, - marker = "(*Marker*)", - list = ["AsyncGetResponse";"GetResponseAsync";"ToString"]) + member private this.VerifyCompListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToStartOfMarker(file, marker) + let completions = AutoCompleteAtCursor(file) + AssertCompListContainsAll(completions, list) - //Regression Test of 4405:intellisense has wrong type for identifier, using most recently bound of same name rather than the one in scope? - [] - member this.``Regression4405.Identifier.ReBound``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f x = - let varA = "string" - let varA = if x then varA(*MarkerRebound*) else 2 - varA""", - marker = "(*MarkerRebound*)", - list = ["Chars";"StartsWith"]) - - //Regression test for FSharp1.0:4702 - [] - member this.``Regression4702.SystemWord``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "System(*Marker*)", - marker = "(*Marker*)", - list = ["Console";"Byte";"ArgumentException"]) + member private this.VerifyCtrlSpaceListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list, ?coffeeBreak:bool, ?addtlRefAssy:string list) = + let coffeeBreak = defaultArg coffeeBreak false + let (solution, project, file) = this.CreateSingleFileProject(fileContents, ?references = addtlRefAssy) + MoveCursorToStartOfMarker(file, marker) + if coffeeBreak then TakeCoffeeBreak(this.VS) + let completions = CtrlSpaceCompleteAtCursor file + AssertCompListContainsAll(completions, list) - [] - member this.``TypeAbbreviation.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest + + member private this.VerifyAutoCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToEndOfMarker(file, marker) + let completions = AutoCompleteAtCursor(file) + AssertEqual(0,completions.Length) - Microsoft.FSharp.Core(*Marker1*)""", - marker = "(*Marker1*)", - list = ["int16";"int32";"int64"]) + member private this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToEndOfMarker(file, marker) + let completions = CtrlSpaceCompleteAtCursor(file) + AssertEqual(0,completions.Length) + + + + // Regression for bug 2116 -- Consider making selected item in completion list case-insensitive + - [] - member this.``TypeAbbreviation.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - Microsoft.FSharp.Core(*Marker1*)""", - marker = "(*Marker1*)", - list = ["Int16";"Int32";"Int64"]) - //Regression test of bug 3754:tupe forwarder bug? intellisense bug? - [] - member this.``Regression3754.TypeOfListForward.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3754 - // tupe forwarder bug? intellisense bug? - - open System.IO - open System.Xml - open System.Xml.Linq - let xmlStr = @" Blah Blah " - let xns = XNamespace.op_Implicit "" - let a = xns + "a" - let reader = new StringReader(xmlStr) - let xdoc = XDocument.Load(reader) - let aElements = [for x in xdoc.Root.Elements() do - if x.Name = a then - yield x] - let href = xns + "href" - aElements |> List(*Marker*)""", - marker = "(*Marker*)", - list = ["append";"choose";"isEmpty"]) - [] - member this.``Regression3754.TypeOfListForward.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3754 - // tupe forwarder bug? intellisense bug? - - open System.IO - open System.Xml - open System.Xml.Linq - let xmlStr = @" Blah Blah " - let xns = XNamespace.op_Implicit "" - let a = xns + "a" - let reader = new StringReader(xmlStr) - let xdoc = XDocument.Load(reader) - let aElements = [for x in xdoc.Root.Elements() do - if x.Name = a then - yield x] - let href = xns + "href" - aElements |> List(*Marker*)""", - marker = "Marker", - list = [""]) +(*------------------------------------------IDE Query automation start -------------------------------------------------*) + member private this.AssertAutoCompletionInQuery(fileContent : string list, marker:string,contained:string list) = + let file = createFile fileContent SourceFileKind.FS ["System.Xml.Linq"] None + + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) + MoveCursorToEndOfMarker(file, marker) + let completions = CompleteAtCursorForReason(file,BackgroundRequestReason.CompleteWord) + AssertCompListContainsAll(completions, contained) + gpatcc.AssertExactly(0,0) - [] - member this.``NonApplicableExtensionMembersDoNotAppear.Bug40379``() = - let code = - [ "open System.Xml.Linq" - "type MyType() =" - " static member Foo(actual:XElement) = actual.Name " - " member public this.Bar1() =" - " let actual1 : int[] = failwith \"\"" - " actual1.(*Marker*)" - " member public this.Bar2() =" - " let actual2 : XNode[] = failwith \"\"" - " actual2.(*Marker*)" - " member public this.Bar3() =" - " let actual3 : XElement[] = failwith \"\"" - " actual3.(*Marker*)" - ] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Xml"; "System.Xml.Linq"]) - MoveCursorToEndOfMarker(file, "actual1.") - let completions = AutoCompleteAtCursor file - AssertCompListDoesNotContainAny(completions, [ "Ancestors"; "AncestorsAndSelf"]) - MoveCursorToEndOfMarker(file, "actual2.") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "Ancestors") - AssertCompListDoesNotContain(completions, "AncestorsAndSelf") - MoveCursorToEndOfMarker(file, "actual3.") - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, ["Ancestors"; "AncestorsAndSelf"]) - [] - member this.``Visibility.InternalMethods.DefInSameAssembly``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module CodeAccessibility - open System - module Module1 = - - type Type1()= - [] - val mutable internal fieldInternal:int - - member internal x.MethodInternal (x:int) = x+2 - - let type1 = new Type1() - type1(*MarkerSameAssemb*)""", - marker = "(*MarkerSameAssemb*)", - list = ["fieldInternal";"MethodInternal"]) + - [] - member this.``QueryExpression.DotCompletionSmokeTest1``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module Basic - let x2 = query { for x in ["1";"2";"3"] do - select x(*Marker*)""", - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs) - [] - member this.``QueryExpression.DotCompletionSmokeTest2``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in ["1";"2";"3"] do select x(*Marker*)""" , - marker = "(*Marker*)", - list = ["Chars"; "Length"], - addtlRefAssy=standard40AssemblyRefs ) - [] - member this.``QueryExpression.DotCompletionSmokeTest0``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = seq { for x in ["1";"2";"3"] do yield x(*Marker*) }""" , - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs ) - [] - member this.``QueryExpression.DotCompletionSmokeTest3``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in ["1";"2";"3"] do select x(*Marker*) }""" , - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs ) - [] - member this.``QueryExpression.DotCompletionSystematic1``() = - for customOperation in ["select";"sortBy";"where"] do - let fileContentsList = - [""" - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" x(*Marker*)""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*)""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*) }""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*) - select x""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" x(*Marker*) - select x }""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*))""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x.Length + x(*Marker*)""" - """ - module Simple - let x2 = query { for x in [1;2;3] do - for y in ["1";"2";"3"] do - """+customOperation+""" (x + y(*Marker*)""" - """ - module Simple - let x2 = query { for x in [1;2;3] do - for y in ["1";"2";"3"] do - """+customOperation+""" (x + y(*Marker*))""" - """ - module Simple - let x2 = query { for x in [1;2;3] do - for y in ["1";"2";"3"] do - where (x > y.Length) - """+customOperation+""" (x + y(*Marker*)""" ] - for fileContents in fileContentsList do - printfn "customOperation = %s, fileContents = <<<%s>>>" customOperation fileContents - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = fileContents, - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs) - [] - member public this.``QueryExpression.InsideJoin.Bug204147``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module Simple - type T() = - member x.GetCollection() = [1;2;3;4] - let q = - query { - for e in [1..10] do - join b in T()(*Marker*) - select b - }""", - marker = "(*Marker*)", - list = ["GetCollection"], - addtlRefAssy=queryAssemblyRefs ) -(*------------------------------------------IDE Query automation start -------------------------------------------------*) member private this.AssertDotCompletionListInQuery(fileContents: string, marker : string, list : string list) = let datacode = """ @@ -7665,129 +1053,14 @@ let rec f l = let completions = DotCompletionAtStartOfMarker file2 marker AssertCompListContainsAll(completions, list) - [] - // Intellisense still appears on arguments when the operator is used in error - member public this.``Query.HasErrors.Bug196230``() = - this.AssertDotCompletionListInQuery( - fileContents = """ - open DataSource - // defined in another file; see AssertDotCompletionListInQuery - let products = Products.getProductList() - let sortedProducts = - query { - for p in products do - let x = p.ProductID + "a" - sortBy p(*Marker*) - select p - }""" , - marker = "(*Marker*)", - list = ["ProductID";"ProductName"] ) // Intellisense still appears on arguments when the operator is used in error - [] - member public this.``Query.HasErrors2``() = - this.AssertDotCompletionListInQuery( - fileContents = """ - open DataSource - let products = Products.getProductList() - let sortedProducts = - query { - for p in products do - orderBy (p(*Marker*)) - }""" , - marker = "(*Marker*)", - list = ["ProductID";"ProductName"] ) - - [] - // Shadowed variables have correct Intellisense - member public this.``Query.ShadowedVariables``() = - this.AssertDotCompletionListInQuery( - fileContents = """ - open DataSource - let products = Products.getProductList() - let p = 12 - let sortedProducts = - query { - for p in products do - select p(*Marker*) - }""" , - marker = "(*Marker*)", - list = ["Category";"ProductName"] ) - - [] - // Intellisense works correctly in a nested query - member public this.``Query.InNestedQuery``() = - let fileContents = """ - let tuples = [ (1, 8, 9); (56, 45, 3)] - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - let foo = - query { - for n in numbers do - let maxNumber = query {for x in tuples do maxBy x(*Marker1*)} - select (n, query {for y in numbers do minBy y(*Marker2*)}) } - """ - this.VerifyDotCompListContainAllAtStartOfMarker(fileContents, "(*Marker1*)", - ["Equals";"GetType"], queryAssemblyRefs ) - this.VerifyDotCompListContainAllAtStartOfMarker(fileContents, "(*Marker2*)", - ["Equals";"CompareTo"], queryAssemblyRefs ) - [] - // Intellisense works correctly in a nested expression within a lamda - member public this.``Query.NestedExpressionWithinLamda``() = - let fileContents = """ - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let f (x : string) = () - let foo = - query { - for n in numbers do - let x = 42 |> ignore; numbers |> List.iter( fun n -> f ("1" + "1")(*Marker*)) - skipWhile (n < 30) - } - """ - this.VerifyDotCompListContainAllAtStartOfMarker(fileContents, "(*Marker*)", - ["Chars";"Length"], queryAssemblyRefs ) - - [] - member this.``Verify no completion on dot after module definition``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - module BasicTest(*Marker*) - let foo x = x - let bar = 1""", - marker = "(*Marker*)") - [] - member this.``Verify no completion after module definition``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ - module BasicTest - - let foo x = x - let bar = 1""", - marker = "module BasicTest ") - [] - member this.``Verify no completion in hash directives``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ - #r (*Marker*) - let foo x = x - let bar = 1""", - marker = "(*Marker*)") - [] - member public this.``ExpressionDotting.Regression.Bug3709``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - let foo = "" - let foo = foo.E(*marker*)n "a" """, - marker = "(*marker*)", - list = ["EndsWith"]) - -// Context project system type UsingProjectSystem() = inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs index ea7f0fa61e8..53519f50758 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs @@ -117,229 +117,6 @@ type UsingMSBuild() as this = else failwithf "The error list number is not the expected %d" num - [] - member public this.``OverloadsAndExtensionMethodsForGenericTypes``() = - let fileContent = - """ -open System.Linq - -type T = - abstract Count : int -> bool - default this.Count(_ : int) = true - - interface System.Collections.Generic.IEnumerable with - member this.GetEnumerator() : System.Collections.Generic.IEnumerator = failwith "not implemented" - interface System.Collections.IEnumerable with - member this.GetEnumerator() : System.Collections.IEnumerator = failwith "not implemented" - -let g (t : T) = t.Count() - """ - this.VerifyNoErrorListAtOpenProject(fileContent) - - - [] - member public this.``ErrorsInScriptFile``() = - let (solution, project, file) = this.CreateSingleFileProject("", fileKind = SourceFileKind.FSX) - - let checkErrors expected = - let l = List.length (GetErrors project) - Assert.Equal(expected, l) - - TakeCoffeeBreak(this.VS) - checkErrors 0 - - ReplaceFileInMemory file <| - [ - "#r \"System\"" - "#r \"System2\"" - ] - TakeCoffeeBreak(this.VS) - checkErrors 1 - - ReplaceFileInMemory file <| - [ - "#r \"System\"" - ] - TakeCoffeeBreak(this.VS) - checkErrors 0 - - [] - member public this.``LineDirective``() = - use _guard = this.UsingNewVS() - let fileContents = """ - # 100 "foo.fs" - let x = y """ - let solution = this.CreateSolution() - let project = CreateProject(solution, "testproject") - let _ = AddFileFromTextBlob(project, "File1.fs", "namespace LineDirectives") - let _ = AddFileFromTextBlob(project,"File2.fs", fileContents) - - let file = OpenFile(project, "File1.fs") - let _ = OpenFile(project,"File2.fs") - Assert.False(Build(project).BuildSucceeded) - - this.VerifyCountAtSpecifiedFile(project,1) - VerifyErrorListContainedExpectedStr("The value or constructor 'y' is not defined",project) - - [] - member public this.``InvalidConstructorOverload``() = - let content = """ - type X private() = - new(_ : int) = X() - new(_ : bool) = X() - new(_ : float, _ : int) = X() - X(1.0) - """ - - let expectedMessages = [ "No overloads match for method 'X'.\u001d\u001dKnown type of argument: float\u001d\u001dAvailable overloads:\u001d - new: bool -> X // Argument at index 1 doesn't match\u001d - new: int -> X // Argument at index 1 doesn't match" ] - - CheckErrorList content (assertExpectedErrorMessages expectedMessages) - - - [] - member public this.``Query.InvalidJoinRelation.GroupJoin``() = - let content = """ -let x = query { - for x in [1] do - groupJoin y in [2] on ( x < y) into g - select x } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("Invalid join relation in 'groupJoin'. Expected 'expr expr', where is =, =?, ?= or ?=?.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - [] - member public this.``Query.NonOpenedNullableModule.Join``() = - let content = """ -let t = - query { - for x in [1] do - join y in [""] on (x ?=? y) - select 1 } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("The operator '?=?' cannot be resolved. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - [] - member public this.``Query.NonOpenedNullableModule.GroupJoin``() = - let content = """ -let t = - query { - for x in [1] do - groupJoin y in [""] on (x ?=? y) into g - select 1 } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("The operator '?=?' cannot be resolved. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - - [] - member public this.``Query.InvalidJoinRelation.Join``() = - let content = """ -let x = - query { - for x in [1] do - join y in [""] on (x > y) - select 1 - } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("Invalid join relation in 'join'. Expected 'expr expr', where is =, =?, ?= or ?=?.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - [] - member public this.``InvalidMethodOverload``() = - let content = """ - System.Console.WriteLine(null) - """ - let expectedMessages = [ "A unique overload for method 'WriteLine' could not be determined based on type information prior to this program point. A type annotation may be needed.\u001d\u001dKnown type of argument: 'a0 when 'a0: null\u001d\u001dCandidates:\u001d - System.Console.WriteLine(buffer: char array) : unit\u001d - System.Console.WriteLine(format: string, [] arg: obj array) : unit\u001d - System.Console.WriteLine(value: obj) : unit\u001d - System.Console.WriteLine(value: string) : unit" ] - CheckErrorList content (assertExpectedErrorMessages expectedMessages) - - [] - member public this.``InvalidMethodOverload2``() = - let content = """ -type A<'T>() = - member this.Do(a : int, b : 'T) = () - member this.Do(a : int, b : int) = () -type B() = - inherit A() - -let b = B() -b.Do(1, 1) - """ - let expectedMessages = [ "A unique overload for method 'Do' could not be determined based on type information prior to this program point. A type annotation may be needed.\u001d\u001dKnown types of arguments: int * int\u001d\u001dCandidates:\u001d - member A.Do: a: int * b: 'T -> unit\u001d - member A.Do: a: int * b: int -> unit" ] - CheckErrorList content (assertExpectedErrorMessages expectedMessages) - - [] - member public this.``NoErrorInErrList``() = - use _guard = this.UsingNewVS() - let fileContents1 = """ - module NoErrors - - open System.Collections.Generic - // but do not use it - """ - let fileContents2 = """ - // Regression test for FSHARP1.0:3824 - Problems with generic type parameters in type extensions (was: Confusing error/warning on type extension: code is less generic) - module NoErrors2 - - module DictionaryExtension = - - type System.Collections.Generic.IDictionary<'k,'v> with - member this.TryLookup(key : 'k) = - let mutable value = Unchecked.defaultof<'v> - if this.TryGetValue(key, &value) then - Some value - else - None - - open DictionaryExtension""" - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let _ = AddFileFromTextBlob(project,"File1.fs", fileContents1) - let _ = OpenFile(project,"File1.fs") - let _ = AddFileFromTextBlob(project,"File2.fs", fileContents2) - let _ = OpenFile(project,"File2.fs") - Build(project) |> ignore - TakeCoffeeBreak(this.VS) - this.VerifyCountAtSpecifiedFile(project,0) - - [] - member public this.``NoLevel4Warning``() = - use _guard = this.UsingNewVS() - let fileContents = """ - namespace testerrorlist - module nolevel4warnings = - let x = System.DateTime.Now - System.DateTime.Now - x.Add(x) |> ignore """ - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let _ = AddFileFromTextBlob(project,"Module1.fs",fileContents) - - let _ = AddFileFromTextBlob(project,"Script.fsx","") - let _ = OpenFile(project,"Script.fsx") - Build(project) |> ignore - - this.VerifyCountAtSpecifiedFile(project,0) - [] //This is an verify action test & example member public this.``TestErrorMessage``() = @@ -347,534 +124,6 @@ b.Do(1, 1) let expectedStr = "The value, namespace, type or module 'Console' is not defined" this.VerifyErrorListContainedExpectedString(fileContent,expectedStr) - [] - member public this.``TestWrongKeywordInInterfaceImplementation``() = - let fileContent = - """ -type staticInInterface = - class - interface System.IDisposable with - static member Foo() = () - member x.Dispose() = () - end - end""" - - CheckErrorList fileContent (function - | err1 :: _ -> - Assert.True(err1.Message.Contains("No static abstract member was found that corresponds to this override")) - | x -> - Assert.Fail(sprintf "Unexpected errors: %A" x)) - - [] - member public this.``TypeProvider.MultipleErrors`` () = - let tpRef = PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll") - let checkList n = - printfn "===TypeProvider.MultipleErrors: %d===" n - let content = sprintf "type Err = TPErrors.TP<%d>" n - let (solution, project, file) = this.CreateSingleFileProject(content, references = [tpRef]) - TakeCoffeeBreak(this.VS) - let errorList = GetErrors(project) - - for err in errorList do - printfn "Severity: %A, Message: %s" err.Severity err.Message - - Assert.True(List.length errorList = n, "Unexpected size of error list") - let uniqueErrors = - errorList - |> Seq.map (fun m -> m.Message, m.Severity) - |> set - Assert.True(uniqueErrors.Count = n, "List should not contain duplicate errors") - for x = 0 to (n - 1) do - let expectedName = sprintf "The type provider 'DummyProviderForLanguageServiceTesting.TypeProviderThatThrowsErrors' reported an error: Error %d" x - Assert.True(Set.contains (expectedName, Microsoft.VisualStudio.FSharp.LanguageService.Severity.Error) uniqueErrors) - - for i = 1 to 10 do - checkList i - - [] - member public this.``Records.ErrorList.IncorrectBindings1``() = - for code in [ "{_}"; "{_ = }"] do - printfn "checking %s" code - CheckErrorList code <| - fun errs -> - printfn "%A" errs - Assert.True((List.length errs) = 2) - assertContains errs "Field bindings must have the form 'id = expr;'" - assertContains errs "'_' cannot be used as field name" - - [] - member public this.``Records.ErrorList.IncorrectBindings2``() = - CheckErrorList "{_ = 1}" <| - function - | [err] -> Assert.Equal("'_' cannot be used as field name", err.Message) - | x -> printfn "%A" x; Assert.Fail("unexpected content of error list") - - [] - member public this.``Records.ErrorList.IncorrectBindings3``() = - CheckErrorList "{a = 1; _; _ = 1}" <| - fun errs -> - Assert.True((List.length errs) = 3) - let groupedErrs = errs |> Seq.groupBy (fun e -> e.Message) |> Seq.toList - Assert.True((List.length groupedErrs) = 2) - for (msg, e) in groupedErrs do - if msg = "'_' cannot be used as field name" then Assert.Equal(2, Seq.length e) - elif msg = "Field bindings must have the form 'id = expr;'" then Assert.Equal(1, Seq.length e) - else Assert.Fail (sprintf "Unexpected message %s" msg) - - - [] - //This test case Verify the Error List shows the correct error message when the static parameter type is invalid - //Intent: We want to make sure that both errors coming from the TP and the compilation of things specific to type provider are properly flagged in the error list. - member public this.``TypeProvider.StaticParameters.IncorrectType `` () = - // dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - // but here as you can see it's give (int * int) - let fileContent = """ type foo = N1.T< const 42,2>""" - let expectedStr = "This expression was expected to have type\u001d 'string' \u001dbut here has type\u001d 'int'" - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify the Error List shows the correct error message when applying invalid static parameter to the provided type - member public this.``TypeProvider.StaticParameters.Incorrect `` () = - - // dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - let fileContent = """ type foo = N1.T< const " ",2>""" - let expectedStr = "An error occurred applying the static arguments to a provided type" - - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify that Error List shows the correct error message when Type Provider that takes two static parameter is given only one static parameter. - member public this.``TypeProvider.StaticParameters.IncorrectNumberOfParameter `` () = - - // dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - // but here as you can see it's give (string) - let fileContent = """type foo = N1.T< const "Hello World">""" - let expectedStr = "The static parameter 'ParamIgnored' of the provided type or method 'T' requires a value. Static parameters to type providers may be optionally specified using named arguments, e.g. 'T'." - - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - [] - member public this.``TypeProvider.ProhibitedMethods`` () = - let cases = - [ - "let x = BadMethods.Arr.GetFirstElement([||])", "GetFirstElement" - "let y = BadMethods.Arr.SetFirstElement([||], 5)", "SetFirstElement" - "let z = BadMethods.Arr.AddressOfFirstElement([||])", "AddressOfFirstElement" - ] - for (code, str) in cases do - this.VerifyErrorListContainedExpectedString - ( - code, - sprintf "The type provider 'DummyProviderForLanguageServiceTesting.TypeProviderThatEmitsBadMethods' reported an error in the context of provided type 'BadMethods.Arr', member '%s'. The error: The operation 'GetMethodImpl' on item 'Int32[]' should not be called on provided type, member or parameter of type 'ProviderImplementation.ProvidedTypes.TypeSymbol'." str, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - ) - - [] - //This test case verify that the Error list count is one in the Error list item when given invalid static parameter that raises an error. - member public this.``TypeProvider.StaticParameters.ErrorListItem `` () = - - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type foo = N1.T< const "Hello World",2>""", - num = 1) - - [] - //This test case Verify that there is No Error list count in the Error list item when the file content is correct. - member public this.``TypeProvider.StaticParameters.NoErrorListCount `` () = - - this.VerifyNoErrorListAtOpenProject( - fileContents = """ - type foo = N1.T< const "Hello World",2>""", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - member public this.``NoError.FlagsAndSettings.TargetOptionsRespected``() = - let fileContent = """ - [] - let fn x = 0 - let y = fn 1""" - // Turn off the "Obsolete" warning. - let (solution, project, file) = this.CreateSingleFileProject(fileContent, disabledWarnings = ["44"]) - - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - let errorList = GetErrors(project) - Assert.True(errorList.IsEmpty) - - [] - member public this.``UnicodeCharacters``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"新規baApplication5") - let _ = AddFileFromTextBlob(project,"新規baProgram.fsi","") - let _ = AddFileFromTextBlob(project,"新規bcrogram.fs","") - - let file = OpenFile(project,"新規baProgram.fsi") - let file = OpenFile(project,"新規bcrogram.fs") - - Assert.False(Build(project).BuildSucceeded) - Assert.True(GetErrors(project) - |> List.exists(fun error -> (error.ToString().Contains("新規baProgram")))) - - // In this bug, particular warns were still present after nowarn - [] - member public this.``NoWarn.Bug5424``() = - let fileContent = """ - #nowarn "67" // this type test or downcast will always hold - #nowarn "66" // this upcast is unnecessary - the types are identical - namespace Namespace1 - module Test = - open System - let a = ((5 :> obj) :?> Object) - let b = a :> obj""" - this.VerifyNoErrorListAtOpenProject(fileContent) - - /// FEATURE: Errors in flags are sent in Error list. - [] - member public this.``FlagsAndSettings.ErrorsInFlagsDisplayed``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - SetVersionFile(project,"nonexistent") - let file = AddFileFromText(project,"File1.fs",[]) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - VerifyErrorListContainedExpectedStr("nonexistent",project) - - [] - member public this.``BackgroundComplier``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - - - module Test - - module M = - let func (args : string[]) = - if(args.Length=1 && args.[0]="Hello") then 0 else 1 - - [] - let main2 args = - let res = func(args) - exit(res) - - let f x = - let p = x - p + 1 - - let g x = - let p = x - p + 1 - """, - num = 2) - - [] - member public this.``CompilerErrorsInErrList1``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - namespace Errorlist - module CompilerError = - - let a = NoVal""", - num = 1 ) - - // [] disabled for F#8, legacy service, covered in FCS tests instead - member public this.``CompilerErrorsInErrList4``() = - this.VerifyNoErrorListAtOpenProject( - fileContents = """ - #nowarn "47" - - type Fruit (shelfLife : int) as x = - - let mutable m_age = (fun () -> x) - - - #nowarn "25" // FS0025: Incomplete pattern matches on this expression. For example, the value 'C' - - type DU = A | B | C - let f x = function A -> true | B -> false - - - - let _fsyacc_gotos = [| 0us; 1us; 2us|] """ ) - - [] - member public this.``CompilerErrorsInErrList5``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - #r "D:\x\Absent.dll" - - let x = 0 """, - num = 1) - - [] - member public this.``CompilerErrorsInErrList6``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type EnumOfBigInt = - | A = 0I - | B = 0I - - type EnumOfNatNum = - | A = 0N - | B = 0N """, - num = 2) - - [] - member public this.``CompilerErrorsInErrList7``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - // FSB 1124, Implement constant literals - type EnumType = - | A = 1 - | B = 2 - - type CustomAttrib(a:int, b:string, c:float, d:EnumType) = - inherit System.Attribute() - - //[] - let a = 42 - //[] - let b = "str" - //[] - let c = 3.141 - //[] - let d = EnumType.A - - [] - type SomeClass() = - override this.ToString() = "SomeClass" - - [] - let main0 args = () - - let foo = 1 """, - num = 5) - - [] - member public this.``CompilerErrorsInErrList8``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type EnumInt8s = | A1 = - 10y """ , - num = 1 ) - - [] - member public this.``CompilerErrorsInErrList9``() = - use _guard = this.UsingNewVS() - let fileContents1 = """ - namespace NS - [] - type Lib() = - class - abstract M : int -> int - end """ - let fileContents2 = """ - namespace NS - module M = - type Lib with - override x.M i = i - """ - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let _ = AddFileFromTextBlob(project,"File1.fs",fileContents1) - let file1 = OpenFile(project,"File1.fs") - let _ = AddFileFromTextBlob(project,"File2.fs",fileContents2) - let file2 = OpenFile(project,"File2.fs") - //this.VerifyErrorListNumberAtOpenProject - this.VerifyCountAtSpecifiedFile(project,1) - TakeCoffeeBreak(this.VS) - Build(project) |> ignore - this.VerifyCountAtSpecifiedFile(project,1) - - [] - member public this.``CompilerErrorsInErrList10``() = - let fileContents = """ - namespace Errorlist - module CompilerError = - - printfn "%A" System.Windows.Forms.Application.UserAppDataPath """ - let (_, project, _) = this.CreateSingleFileProject(fileContents, references = ["PresentationCore.dll"; "PresentationFramework.dll"]) - Build(project) |> ignore - - this.VerifyCountAtSpecifiedFile(project,1) - - [] - member public this.``DoubleClickErrorListItem``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - let x = x """, - num = 1) - [] - member public this.``FixingCodeAfterBuildRemovesErrors01``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - let x = 4 + "x" """, - num = 2) - - [] - member public this.``FixingCodeAfterBuildRemovesErrors02``() = - this.VerifyNoErrorListAtOpenProject( - fileContents = "let x = 4" ) - - [] - member public this.``IncompleteExpression``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - // Regression test for FSHARP1.0:1397 - Warning required on expr of function type who result is immediately thrown away - module Test - - printfn "%A" - - List.map (fun x -> x + 1) """ , - num = 2) - - [] - member public this.``IntellisenseRequest``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type Foo() = - member a.B(*Marker*) : int = "1" """, - num = 1) - - [] - member public this.``TypeChecking1``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - - x.Next <- Some x """, - num = 1) - - [] - member public this.``TypeChecking2``() = - this.VerifyErrorListContainedExpectedString( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - - x.Next <- Some x """, - expectedStr = "Foo.Thread option") - - [] - member public this.``TypeChecking3``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - x.Next <- Some 1 """, - num = 1) - - [] - member public this.``TypeChecking4``() = - this.VerifyErrorListContainedExpectedString( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - x.Next <- Some 1 """, - expectedStr = "operator '-'" ) - -(* TODO why does this portion not work? specifically, last assert fails - printfn "changing file..." - ReplaceFileInMemory file1 [ - "let xx = \"foo\"" // now x is string - "printfn \"hi\""] - - // assert p1 xx is string - MoveCursorToEndOfMarker(file1,"let x") - TakeCoffeeBreak(this.VS) - let tooltip = GetQuickInfoAtCursor file1 - AssertContains(tooltip,"string") - - // assert p2 yy is int - MoveCursorToEndOfMarker(file2,"let y") - let tooltip = GetQuickInfoAtCursor file2 - AssertContains(tooltip,"int") - - AssertNoErrorsOrWarnings(project1) - AssertNoErrorsOrWarnings(project2) - - printfn "rebuilding dependent project..." - // (re)build p1 (with xx now string) - Build(project1) |> ignore - TakeCoffeeBreak(this.VS) - - AssertNoErrorsOrWarnings(project1) - AssertNoErrorsOrWarnings(project2) - - // assert p2 yy is now string - MoveCursorToEndOfMarker(file2,"let y") - let tooltip = GetQuickInfoAtCursor file2 - AssertContains(tooltip,"string") -*) - - [] - member public this.``Warning.ConsistentWithLanguageService``() = - let fileContent = """ - open System - mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin - mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" - let (_, project, file) = this.CreateSingleFileProject(fileContent, fileKind = SourceFileKind.FSX) - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - let warnList = GetWarnings(project) - Assert.Equal(20,warnList.Length) - - [] - member public this.``Warning.ConsistentWithLanguageService.Comment``() = - let fileContent = """ - open System - //mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin - //mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" - let (_, project, file) = this.CreateSingleFileProject(fileContent, fileKind = SourceFileKind.FSX) - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - let warnList = GetWarnings(project) - Assert.Equal(0,warnList.Length) - - [] - member public this.``Errorlist.WorkwithoutNowarning``() = - let fileContent = """ - type Fruit (shelfLife : int) as x = - let mutable m_age = (fun () -> x) - #nowarn "47" - """ - let (_, project, file) = this.CreateSingleFileProject(fileContent) - - Assert.True(Build(project).BuildSucceeded) - TakeCoffeeBreak(this.VS) - let warnList = GetErrors(project) - Assert.Equal(1,warnList.Length) - -// Context project system type UsingProjectSystem() = inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs index e38c503c17d..7872714b264 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs @@ -28,17 +28,6 @@ type UsingMSBuild() = |> Seq.exists (fun errorMessage -> errorMessage.Contains(expectedStr))) - // Not a recovery case, but make sure we get a squiggle at the unfinished Main() - [] - member public this.``ErrorRecovery.Bug4538_3``() = - let fileContent = """ - type MyType() = - override x.ToString() = "" - let Main() = - let x = MyType()""" - let expectedStr = "The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result." - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr) - // Not a recovery case, but make sure we get a squiggle at the unfinished Main() [] member public this.``ErrorRecovery.Bug4538_4``() = @@ -50,208 +39,7 @@ type UsingMSBuild() = let expectedStr = "The block following this 'use' is unfinished. Every code block is an expression and must have a result. 'use' cannot be the final code element in a block. Consider giving this block an explicit result." this.VerifyErrorListContainedExpectedString(fileContent,expectedStr) - [] - member public this.``ErrorRecovery.Bug4881_1``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif s." - "else ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - [] - member public this.``ErrorRecovery.Bug4881_2``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif true" - "elif s." - "else ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - [] - member public this.``ErrorRecovery.Bug4881_3``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif s." - "elif true" - "else ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - - [] - member public this.``ErrorRecovery.Bug4881_4``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif s." - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - - // This case was fixed while investigating 4538. - [] - member public this.``ErrorRecovery.NotFixing4538_1``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = new MyT" - " ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"new MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - // This case was fixed while investigating 4538. - [] - member public this.``ErrorRecovery.NotFixing4538_2``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = MyT" - " ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"= MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - // This case was fixed while investigating 4538. - [] - member public this.``ErrorRecovery.NotFixing4538_3``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"= MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - [] - member public this.``ErrorRecovery.Bug4538_1``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - - MoveCursorToEndOfMarker(file,"= MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - [] - member public this.``ErrorRecovery.Bug4538_2``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let x = MyType()" - " let _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"_ = MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - - - - - [] - member public this.``ErrorRecovery.Bug4538_5``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " use x = null" - " use _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"_ = MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - - [] - member public this.``ErrorRecovery.Bug4594_1``() = - let code = - ["let Bar(xyz) =" - " let hello =" - " if x" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"if x") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"xyz") - - /// In this bug, the Module. at the very end of the file was treated as if it were in the scope - /// of Module rather than right after it. This check just makes sure we can see a data tip because - /// Module is available. - [] - member public this.``ErrorRecovery.5878_1``() = - Helper.AssertMemberDataTipContainsInOrder - ( - this.TestRunner, - (*code *) - [ - "module Module =" - " /// Union comment" - " type Union =" - " /// Case comment" - " | Case of int" - "Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Case", - (* expect to see in order... *) - [ - "union case Module.Union.Case: int -> Module.Union"; - "Case comment"; - ] - ) - // Context project system type UsingProjectSystem() = - inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) \ No newline at end of file + inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs index 59dab3c110e..0e4d9c18f39 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs @@ -125,73 +125,6 @@ type UsingMSBuild() = let projFileText = System.IO.File.ReadAllText(ProjectFile(project)) AssertMatchesRegex '<' @"\s*\s*link.fs" projFileText - [] - member public this.``Lexer.CommentsLexing.Bug1548``() = - let scan = new FSharpScanner_DEPRECATED(fun source -> - let fileName = "test.fs" - let defines = [ "COMPILED"; "EDITING" ] - - FSharpSourceTokenizer(defines,Some(fileName), None, None).CreateLineTokenizer(source)) - - let cm = Microsoft.VisualStudio.FSharp.LanguageService.TokenColor.Comment - let kw = Microsoft.VisualStudio.FSharp.LanguageService.TokenColor.Keyword - - // This specifies the source code to test and a collection of tokens that - // we want to find in the result (note: it doesn't have to contain every token, because - // behavior for some of them is undefined - e.g. "(* "\"*)" - what is token here? - let sources = - [ "// some comment", - [ (0, 1), cm; (2, 2), cm; (3, 6), cm; (7, 7), cm; (8, 14), cm ] - "// (* hello // 12345\nlet", - [ (6, 10), cm; (15, 19), cm; (0, 2), kw ] // checks 'hello', '12345' and keyword 'let' - "//- test", - [ (0, 2), cm; (4, 7), cm ] // checks whether '//-' isn't treated as an operator - - /// same thing for XML comments - these are treated in a different lexer branch - "/// some comment", - [ (0, 2), cm; (3, 3), cm; (4, 7), cm; (8, 8), cm; (9, 15), cm ] - "/// (* hello // 12345\nmember", - [ (7, 11), cm; (16, 20), cm; (0, 5), kw ] - "///- test", - [ (0, 3), cm; (5, 8), cm ] - - //// same thing for "////" - these are treated in a different lexer branch - "//// some comment", - [ (0, 3), cm; (4, 4), cm; (5, 8), cm; (9, 9), cm; (10, 16), cm ] - "//// (* hello // 12345\nlet", - [ (8, 12), cm; (17, 21), cm; (0, 2), kw ] - "////- test", - [ (0, 4), cm; (6, 9), cm ] - - "(* test 123 (* 456 nested *) comments *)", - [ (3, 6), cm; (8, 10), cm; (15, 17), cm; (19, 24), cm; (29, 36), cm ] // checks 'test', '123', '456', 'nested', 'comments' - "(* \"with 123 \\\" *)\" string *)", - [ (4, 7), cm; (9, 11), cm; (20, 25), cm ] // checks 'with', '123', 'string' - "(* @\"with 123 \"\" *)\" string *)", - [ (5, 8), cm; (10, 12), cm; (21, 26), cm ] // checks 'with', '123', 'string' - ] - - for lineText, expected in sources do - scan.SetLineText lineText - - let currentTokenInfo = new Microsoft.VisualStudio.FSharp.LanguageService.TokenInfo() - let lastColorState = 0 // First line of code, so no previous state - currentTokenInfo.EndIndex <- -1 - let refState = ref (ColorStateLookup_DEPRECATED.LexStateOfColorState lastColorState) - - // Lex the line and add all lexed tokens to a dictionary - let lexed = new System.Collections.Generic.Dictionary<_, _>() - while scan.ScanTokenAndProvideInfoAboutIt(1, currentTokenInfo, refState) do - lexed.Add( (currentTokenInfo.StartIndex, currentTokenInfo.EndIndex), currentTokenInfo.Color ) - - // Verify that all tokens in the specified list occur in the lexed result - for pos, clr in expected do - let (succ, v) = lexed.TryGetValue(pos) - let found = lexed |> Seq.map (fun kvp -> kvp.Key, kvp.Value) |> Seq.toList - AssertEqualWithMessage(true, succ, sprintf "Cannot find token %A at %A in %A\nFound: %A" clr pos lineText found) - AssertEqualWithMessage(clr, v, sprintf "Wrong color of token %A at %A in %A\nFound: %A" clr pos lineText found) - - // This was a bug in ReplaceAllText (subsequent calls to SetMarker would fail) [] member public this.``Salsa.ReplaceAllText``() = @@ -246,167 +179,6 @@ type UsingMSBuild() = Helper.AssertListContainsInOrder(GetOutputWindowPaneLines(this.VS), ["error FS0041: A unique overload for method 'Plot' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: member N.M.LineChart.Plot : f:(float -> float) * xmin:float * xmax:float -> unit, member N.M.LineChart.Plot : f:System.Func * xmin:float * xmax:float -> unit"]) - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAsserted``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ """let F() = """ - """ if true then [], """ - """ elif true then [],"" """ - """ else [],"" """ ] - ) - - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedToo``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ "type C() = " - " member this.F() = ()" - " interface System.IComparable with " - " member _.CompareTo(v:obj) = 1" ] - ) - - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedThree``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ "type Foo =" - " { mutable Data: string }" - " member x.XmlDocSig " - " with get() = x.Data" - " and set(v) = x.Data <- v" ] - ) - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedFour``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ "let y=new" - "let z=4" ] - ) - - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedFive``() = - Helper.ExhaustivelyScrutinize(this.TestRunner, [ """CSV.File<@"File1.txt">.[0].""" ]) // <@ is one token, wanted < @"... - - [] - member public this.``ExhaustivelyScrutinize.Bug2277``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "open Microsoft.FSharp.Plot.Excel" - "open Microsoft.FSharp.Plot.Interactive" - "let ps = [| (1.,\"c\"); (-2.,\"p\") |]" - "plot (Bars(ps))" - "let xs = [| 1.0 .. 20.0 |]" - "let ys = [| 2.0 .. 21.0 |]" - "let pp= plot(Area(xs,ys))" ] - ) - - [] - member public this.``ExhaustivelyScrutinize.Bug2283``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#r \"NestedClasses.dll\"" // Scenario requires this assembly not exist. - "//753 atomType -> atomType DOT path typeArgs" - "let specificIdent (x : RootNamespace.ClassOfT.NestedClassOfU) = x" - "let x = new RootNamespace.ClassOfT.NestedClassOfU()" - "if specificIdent x <> x then exit 1" - "exit 0"] - ) - - - /// Verifies that token info returns correct trigger classes - /// - this is used in MPF for triggering various intellisense features - [] - member public this.``TokenInfo.TriggerClasses``() = - let important = - [ // Member select for dot completions - Parser.DOT, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter,FSharpTokenTriggerClass.MemberSelect) - // for parameter info - Parser.LPAREN, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamStart ||| FSharpTokenTriggerClass.MatchBraces) - Parser.COMMA, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamNext) - Parser.RPAREN, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamEnd ||| FSharpTokenTriggerClass.MatchBraces) ] - let matching = - [ // Other cases where we expect MatchBraces - Parser.LQUOTE("", false); Parser.LBRACK; Parser.LBRACE (Unchecked.defaultof<_>); Parser.LBRACK_BAR; - Parser.RQUOTE("", false); Parser.RBRACK; Parser.RBRACE (Unchecked.defaultof<_>); Parser.BAR_RBRACK ] - |> List.map (fun n -> n, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.MatchBraces)) - for tok, expected in List.concat [ important; matching ] do - let info = TestExpose.TokenInfo tok - AssertEqual(expected, info) - - [] - member public this.``MatchingBraces.VerifyMatches``() = - let content = - [| - " - let x = (1, 2)//1 - let y = ( 3 + 1 ) * 2 - let z = - async { - return 10 - } - let lst = - [// list_start - 1;2;3 - ]//list_end - let arr = - [| - 1 - 2 - |] - let quote = <@(* S0 *) 1 @>(* E0 *) - let quoteWithNestedList = <@(* S1 *) ['x';'y';'z'](* E_L*) @>(* E1 *) - [< System.Serializable() >] - type T = class end - " - |] - let (_solution, _project, file) = this.CreateSingleFileProject(String.concat Environment.NewLine content) - - let getPos marker = - // fix 1-based positions to 0-based - MoveCursorToStartOfMarker(file, marker) - let (row, col) = GetCursorLocation(file) - (row - 1), (col - 1) - - let setPos row col = - // fix 0-based positions to 1-based - MoveCursorTo(file, row + 1, col + 1) - - let checkBraces startMarker endMarker expectedSpanLen = - let (startRow, startCol) = getPos startMarker - let (endRow, endCol) = getPos endMarker - - let checkTextSpan (actual : TextSpan) expectedRow expectedCol = - Assert.True(actual.iStartLine = actual.iEndLine, "Start and end of the span should be on the same line") - Assert.Equal(expectedRow, actual.iStartLine) - Assert.Equal(expectedCol, actual.iStartIndex) - Assert.True(actual.iEndIndex = (actual.iStartIndex + expectedSpanLen), sprintf "Span should have length == %d" expectedSpanLen) - - let checkBracesForPosition row col = - setPos row col - let braces = GetMatchingBracesForPositionAtCursor(file) - Assert.Equal(1, braces.Length) - - let (lbrace, rbrace) = braces.[0] - checkTextSpan lbrace startRow startCol - checkTextSpan rbrace endRow endCol - - checkBracesForPosition startRow startCol - checkBracesForPosition endRow endCol - - checkBraces "(1" ")//1" 1 - checkBraces "( " ") *" 1 - checkBraces "{" "}" 1 - checkBraces "[// list_start" "]//list_end" 1 - checkBraces "[|" "|]" 2 - checkBraces "<@(* S0 *)" "@>(* E0 *)" 2 - checkBraces "<@(* S1 *)" "@>(* E1 *)" 2 - checkBraces "['x'" "](* E_L*)" 1 - checkBraces "[<" ">]" 2 - - // Context project system type UsingProjectSystem() = inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs index 3e115779423..cd130c5d97a 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs @@ -83,402 +83,12 @@ type UsingMSBuild() = file result - [] - member this.``Operators.TopLevel``() = - this.VerifyGotoDefnSuccessForNonIdentifierAtStartOfMarker( - fileContents = """ - let (===) a b = a = b - let _ = 1 === 2 - """, - marker = "=== 2", - pos=(1,21) - ) - [] - member this.``Operators.Member``() = - this.VerifyGotoDefnSuccessForNonIdentifierAtStartOfMarker( - fileContents = """ - type U = U - with - static member (+++) (U, U) = U - let _ = U +++ U - """, - marker = "++ U", - pos=(3,35) - ) - [] - member public this.``Value``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - type DiscUnion = - | Alpha of string - | Beta of decimal * unit - | Gamma - - let valueX = Beta(1.0M, ())(*GotoTypeDef*) - let valueY = valueX (*GotoValDef*) - """, - marker = "valueX (*GotoValDef*)", - definitionCode = "let valueX = Beta(1.0M, ())(*GotoTypeDef*)") - [] - member public this.``DisUnionMember``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - type DiscUnion = - | Alpha of string - | Beta of decimal * unit - | Gamma - - let valueX = Beta(1.0M, ())(*GotoTypeDef*) - let valueY = valueX (*GotoValDef*) - """, - marker = "Beta(1.0M, ())(*GotoTypeDef*)", - definitionCode = "| Beta of decimal * unit") - [] - member public this.``PrimitiveType``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - // Can't goto def on an int literal - let bi = 123456I""", - marker = "123456I") - [] - member public this.``OnTypeDefinition``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2516 - type One (*Marker1*) = One - let f (x : One (*Marker2*)) = 2 - """, - marker = "One (*Marker1*)", - definitionCode = "type One (*Marker1*) = One") - [] - member public this.``Parameter``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2516 - type One (*Marker1*) = One - let f (x : One (*Marker2*)) = 2 - """, - marker = "One (*Marker2*)", - definitionCode = "type One (*Marker1*) = One") - - // This test case check the GotoDefinition (i.e. the TypeProviderDefinitionLocation Attribute) - // We expect the correct FilePath, Line and Column on provided: Type, Event, Method, and Property - // TODO: add a case for a provided Field - [] - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute``() = - use _guard = this.UsingNewVS() - // Note that the verification helped method is custom because we *do* care about the column as well, - // which is something that the general purpose method in this file (surprisingly!) does not do. - let VerifyGoToDefnSuccessAtStartOfMarkerColumn(fileContents : string, marker : string, definitionCode : string, typeProviderAssembly : string, columnMarker : string) = - let (sln, proj, file) = GlobalFunctions.CreateNamedSingleFileProject (this.VS, (fileContents, "File.fs")) - - // Add reference to the type provider - this.AddAssemblyReference(proj,typeProviderAssembly) - - // Identify (line,col) of the destination, i.e. where we expect to land after hitting F12 - // We do this to avoid hardcoding absolute numbers in the code. - MoveCursorToStartOfMarker (file,columnMarker) - let _,column = GetCursorLocation(file) - - // Put cursor at start of marker and then hit F12 - MoveCursorToStartOfMarker (file, marker) - let identifier = (GetIdentifierAtCursor file).Value |> fst - let result = GotoDefinitionAtCursor file - - // Execute validation (on file name and line) - CheckGotoDefnResult - (GotoDefnSuccess identifier definitionCode) - file - result - - // Reminder: coordinates in the F# compiler are 1-based for lines, and 0-based for columns - // coordinates from type providers are 1-based for both lines and columns - // GetCursorLocation() seems to return something even more off by 1... - let column' = column - 2 - - match result.ToOption() with - | Some(span,_) -> Assert.Equal(column',span.iStartIndex) - | None -> failwithf "Expected to find the definition at column '%d' but GotoDefn failed." column' - - // Basic scenario on a provided Type - let ``Type.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let a = typeof - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "T(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // This test case checks the type with space in between like N.``T T`` for GotoDefinition - let ``Type.SpaceInTheType``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let a = typeof - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "T``", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttributeWithSpaceInTheType.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Constructor - let ``Constructor.BasicScenario``() = - - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let foo = new N.T(*GotoValDef*)() - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "T(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Method - let ``Method.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let t = new N.T.M(*GotoValDef*)() - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "M(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Property - let ``Property.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let p = N.T.StaticProp(*GotoValDef*) - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "StaticProp(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Event - let ``Event.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let t = new N.T() - t.Event1(*GotoValDef*) - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "Event1(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Actually execute all the scenarios... - ``Type.BasicScenario``() - ``Type.SpaceInTheType``() - ``Constructor.BasicScenario``() - ``Method.BasicScenario``() - ``Property.BasicScenario``() - ``Event.BasicScenario``() - - - [] - member public this.``GotoDefinition.NoSourceCodeAvailable``() = - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = "System.String.Format(\"\")", - marker = "ormat", - f = (fun (_, result) -> - Assert.False(result.Success) - Assert.True(result.ErrorDescription.Contains("Source code is not available")) - ) - ) - - [] - member public this.``GotoDefinition.NoIdentifierAtLocation``() = - let useCases = - [ - "let x = 1", "1" - "let x = 1.2", ".2" - "let x = \"123\"", "2" - ] - for (source, marker) in useCases do - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = source, - marker = marker, - f = (fun (_, result) -> - Assert.False(result.Success) - Assert.True(result.ErrorDescription.Contains("Cursor is not on identifier")) - ) - ) - - [] - member public this.``GotoDefinition.ProvidedTypeNoDefinitionLocationAttribute``() = - - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = """ - type T = N1.T<"", 1> - """, - marker = "T<", - f = (fun (_, result) -> Assert.False(result.Success) ), - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - ) - - [] - member public this.``GotoDefinition.ProvidedMemberNoDefinitionLocationAttribute``() = - let useCases = - [ - """ - type T = N1.T<"", 1> - T.Param1 - """, "ram1", "Param1" - - """ - type T = N1.T1 - T.M1(1) - """, "1(", "M1" - ] - - for (source, marker, name) in useCases do - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = source, - marker = marker, - f = (fun (_, result) -> - Assert.False(result.Success) - let expectedText = sprintf "provided member '%s'" name - Assert.True(result.ErrorDescription.Contains(expectedText)) - ), - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - ) - [] - // This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Type - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let a = typeof - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "T(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - //This test case is when the TypeProviderDefinitionLocationAttribute Line doesn't exist for TypeProvider Type - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.LineDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let a = typeof - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "T(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeLineDoesnotExist.dll")]) - - [] - // This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Constructor - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Constructor.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let foo = new N.T(*GotoValDef*)() - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "T(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - - - [] - //This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Method - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Method.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let t = new N.T.M(*GotoValDef*)() - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "M(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - // This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Property - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Property.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let p = N.T.StaticProp(*GotoValDef*) - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "StaticProp(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - //This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Event - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Event.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let t = new N.T() - t.Event1(*GotoValDef*) - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "Event1(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - member public this.``ModuleDefinition``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2517 - module Foo (*MarkerModuleDefinition*) = - let x = () - """, - marker = "Foo (*MarkerModuleDefinition*)", - definitionCode = "module Foo (*MarkerModuleDefinition*) =") - - [] - member public this.``Record.Field.Definition``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2518 - type MyRec = - { myX (*MarkerXFieldDefinition*) : int - myY (*MarkerYFieldDefinition*) : int - } - let rDefault = - { myX (*MarkerXField*) = 2 - myY (*MarkerYField*) = 3 - } - """, - marker = "myX (*MarkerXFieldDefinition*)", - definitionCode = "{ myX (*MarkerXFieldDefinition*) : int") - - [] - member public this.``Record.Field.Usage``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2518 - type MyRec = - { myX (*MarkerXFieldDefinition*) : int - myY (*MarkerYFieldDefinition*) : int - } - let rDefault = - { myX (*MarkerXField*) = 2 - myY (*MarkerYField*) = 3 - } - """, - marker = "myY (*MarkerYField*)", - definitionCode = " myY (*MarkerYFieldDefinition*) : int") /// run a GotoDefinition test where the expected result is a file that we /// have an `OpenFile` handle for (this won't work, e.g., if this file is a @@ -524,108 +134,9 @@ type UsingMSBuild() = member this.GotoDefinitionTestWithSimpleFile (startLoc : string)(exp : (string * string) option) : unit = this.SolutionGotoDefinitionTestWithSimpleFile startLoc exp - [] - member this.``GotoDefinition.OverloadResolution``() = - let lines = - [ "type D() =" - " override this.#3#ToString() = System.String.Empty" - " member this.#4#ToString(s : string) = ()" - "" - " member this.#1#Foo() = ()" - " member this.#2#Foo(x) = ()" - "" - "let d = new D()" - "d.Foo$1$()" - "d.Foo$2$(1)" - "d.ToString$3$()" - "d.ToString$4$(\"aaa\") " - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.OverloadResolutionForProperties``() = - let lines = [ "type D() =" - " member this.#1##2#Foo" - " with get(i:int) = 1" - " and set (i:int) v = ()" - "" - " member this.#3##4#Foo" - " with get (s:string) = 1" - " and set (s:string) v = ()" - "" - "D().$1$Foo 1" - "D().$2$Foo 1 <- 2" - "D().$3$Foo \"abc\"" - "D().$4$Foo \"abc\" <- 2" - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.OverloadResolutionWithOverrides``() = - let lines = - [ "[]" - "type Base<'T>() =" - " member this.#2#Method() = ()" - " abstract Method : 'T -> unit" - "" - "type Derived() =" - " inherit Base()" - "" - " override this.#1#Method (i:int) = ()" - "" - "let d = new Derived()" - "d.$1$Method 12" - "d.$2$Method()" - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.OverloadResolutionStatics``() = - let lines = - [ "type T =" - " static member #1#Foo(i : int) = ()" - " static member #2#Foo(s : string) = ()" - "" - "T.$1$Foo 1" - "T.$2$Foo \"abc\"" - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.Constructors``() = - let lines = - [ "type #1a##1b##1c##1d#B() =" - " #2a##2b##2c##2d#new(i : int) = B()" - " #3a##3b##3c##3d#new(s : string) = B()" - "" - "B()" - "B(1)" - "B(\"abc\")" - "" - "new $1b$B()" - "new $2b$B(1)" - "new $3b$B(\"abc\")" - "" - "type D1() =" - " inherit $1c$B()" - "" - "type D2() =" - " inherit $2c$B(1)" - - "type D3() =" - " inherit $3c$B(\"abc\")" - "" - "let o1 = { new $1d$B() with" - " override this.ToString() = \"\"" - " }" - "let o2 = { new $2d$B(1) with" - " override this.ToString() = \"\"" - " }" - "let o2 = { new $3d$B(\"aaa\") with" - " override this.ToString() = \"\"" - " }" - - ] - this.GotoDefinitionTestWithMarkup lines member internal this.GotoDefinitionTestWithMarkup (lines : string list) = let origins = Dictionary() @@ -873,452 +384,85 @@ type UsingMSBuild() = // ensure that we've found the correct position (i.e., these must be unique // in any given test source file) - [] - member this.``GotoDefinition.InheritedMembers``() = - let lines = - [ "[]" - "type Foo() =" - " abstract Method : unit -> unit" - " abstract Property : int" - "type Bar() =" - " inherit Foo()" - " override this.Method () = ()" - " override this.Property = 1" - "let b = Bar()" - "b.Method(*loc-1*)()" - "b.Property(*loc-2*)" - ] - this.SolutionGotoDefinitionTestWithLines lines "Method(*loc-1*)" (Some("override this.Method () = ()","this.Method")) - this.SolutionGotoDefinitionTestWithLines lines "Property(*loc-2*)" (Some("override this.Property = 1","this.Property")) - /// let #x = () in $x - [] - member public this.``GotoDefinition.InsideClass.Bug3176`` () = - this.GotoDefinitionTestWithSimpleFile "id77 (*loc-77*)" (Some("val id77 (*loc-77*) : int", "id77")) /// let #x = () in $x [] member public this.``GotoDefinition.Simple.Binding.TrivialLetRHS`` () = this.GotoDefinitionTestWithSimpleFile "x (*loc-1*)" (Some("let x = () (*loc-2*)", "x")) - /// let #x = () in x$ - [] - member public this.``GotoDefinition.Simple.Binding.TrivialLetRHSToRight`` () = - this.GotoDefinitionTestWithSimpleFile " (*loc-1*)" (Some("let x = () (*loc-2*)", "x")) - /// let $x = () in x - [] - member public this.``GotoDefinition.Simple.Binding.TrivialLetLHS`` () = - this.GotoDefinitionTestWithSimpleFile "x = () (*loc-2*)" (Some("let x = () (*loc-2*)", "x")) - /// let x = () in let #x = () in $x - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithSameNameRHS`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-4*)" (Some("let x = () (*loc-3*)", "x")) - /// let x = () in let $x = () in x - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithSameNameLHSInner`` () = - this.GotoDefinitionTestWithSimpleFile "x = () (*loc-3*)" (Some("let x = () (*loc-3*)", "x")) - /// let $x = () in let x = () in x - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithSameNameLHSOuter`` () = - this.GotoDefinitionTestWithSimpleFile "x = () (*loc-5*)" (Some("let x = () (*loc-5*)", "x")) - /// let #x = () in let x = $x in () - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithXIsX`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-6*)" (Some("let x = () (*loc-7*)", "x")) - /// let x = () in let rec #x = fun y -> $x y in () - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithXRec`` () = - this.GotoDefinitionTestWithSimpleFile "x y (*loc-8*)" (Some("let rec x = (*loc-9*)", "x")) - /// let x = () in let rec x = fun #y -> x $y in () - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithXRecParam`` () = - this.GotoDefinitionTestWithSimpleFile "y (*loc-8*)" (Some("fun y -> (*loc-10*)", "y")) - /// let #(+) x _ = x in 2 $+ 3 - [] - member public this.``GotoDefinition.Simple.Binding.Operator`` () = - this.GotoDefinitionTestWithSimpleFile "+ 3 (*loc-11*)" (Some("let (+) x _ = x (*loc-2*)", "+")) - /// type #Zero = - /// let f (_ : $Zero) = 0 - [] - member public this.``GotoDefinition.Simple.Datatype.NullType`` () = - this.GotoDefinitionTestWithSimpleFile "Zero) : 'a = failwith \"hi\" (*loc-14*)" (Some("type Zero = (*loc-13*)", "Zero")) - /// type One = $One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeConsDef`` () = - this.GotoDefinitionTestWithSimpleFile "One (*loc-15*)" (Some("One (*loc-15*)", "One")) - /// type $One = One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeTypenameDef`` () = - this.GotoDefinitionTestWithSimpleFile "One = (*loc-16*)" (Some("type One = (*loc-16*)", "One")) - /// type One = #One - /// let f (_ : One) = $One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeCons`` () = - this.GotoDefinitionTestWithSimpleFile "One (*loc-18*)" (Some("One (*loc-15*)", "One")) - /// type #One = One - /// let f (_ : $One) = One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeTypename`` () = - this.GotoDefinitionTestWithSimpleFile "One) = (*loc-17*)" (Some("type One = (*loc-16*)", "One")) - /// type $Nat = Suc of Nat | Zro - [] - member public this.``GotoDefinition.Simple.Datatype.NatTypeTypenameDef`` () = - this.GotoDefinitionTestWithSimpleFile "Nat = (*loc-19*)" (Some("type Nat = (*loc-19*)", "Nat")) - /// type #Nat = Suc of $Nat | Zro - [] - member public this.``GotoDefinition.Simple.Datatype.NatTypeConsArg`` () = - this.GotoDefinitionTestWithSimpleFile "Nat (*loc-20*)" (Some("type Nat = (*loc-19*)", "Nat")) - /// type Nat = Suc of Nat | #Zro - /// fun m -> match m with | $Zro -> () | _ -> () - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatZro`` () = - this.GotoDefinitionTestWithSimpleFile "Zro -> (*loc-24*)" (Some("| Zro (*loc-21*)", "Zro")) - /// type Nat = $Suc of Nat | Zro - /// fun m -> match m with | Zro -> () | $Suc _ -> () - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatSuc`` () = - this.GotoDefinitionTestWithSimpleFile "Suc m -> (*loc-25*)" (Some("| Suc of Nat (*loc-20*)", "Suc")) - /// let rec plus m n = match m with | Zro -> n | Suc #m -> Suc (plus $m n) - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatSucVarUse`` () = - this.GotoDefinitionTestWithSimpleFile "m n) (*loc-26*)" (Some("| Suc m -> (*loc-25*)", "m")) - /// let rec plus m n = match m with | Zro -> n | Suc #m -> Suc (plus $m n) - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatSucOuterVarUse`` () = - this.GotoDefinitionTestWithSimpleFile "n) (*loc-26*)" (Some("let rec plus m n = (*loc-23*)", "n")) - /// type $MyRec = { myX : int ; myY : int } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordTypenameDef`` () = - this.GotoDefinitionTestWithSimpleFile "MyRec = (*loc-27*)" (Some("type MyRec = (*loc-27*)", "MyRec")) - /// type MyRec = { $myX : int ; myY : int } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField1Def`` () = - this.GotoDefinitionTestWithSimpleFile "myX : int (*loc-28*)" (Some("{ myX : int (*loc-28*)", "myX")) - /// type MyRec = { myX : int ; $myY : int } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField2Def`` () = - this.GotoDefinitionTestWithSimpleFile "myY : int (*loc-29*)" (Some("myY : int (*loc-29*)", "myY")) - /// type MyRec = { #myX : int ; myY : int } - /// let rDefault = { $myX = 2 ; myY = 3 } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField1Use`` () = - this.GotoDefinitionTestWithSimpleFile "myX = 2 (*loc-30*)" (Some("{ myX : int (*loc-28*)", "myX")) - /// type MyRec = { myX : int ; #myY : int } - /// let rDefault = { myX = 2 ; $myY = 3 } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField2Use`` () = - this.GotoDefinitionTestWithSimpleFile "myY = 3 (*loc-31*)" (Some("myY : int (*loc-29*)", "myY")) - /// type MyRec = { #myX : int ; myY : int } - /// let rDefault = { myX = 2 ; myY = 3 } - /// let _ = { rDefault with $myX = 7 } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField1UseInWith`` () = - this.GotoDefinitionTestWithSimpleFile "myX = 7 } (*loc-32*)" (Some("{ myX : int (*loc-28*)", "myX")) - /// let a = () in let id (x : '$a) : 'a = x - [] - member public this.``GotoDefinition.Simple.Polymorph.Leftmost`` () = - this.GotoDefinitionTestWithSimpleFile "a) (*loc-33*)" (Some("let id (x : 'a) (*loc-33*)", "'a")) - /// let a = () in let id (x : 'a) : '$a = x - [] - member public this.``GotoDefinition.Simple.Polymorph.NotLeftmost`` () = - this.GotoDefinitionTestWithSimpleFile "a = x (*loc-34*)" (Some("let id (x : 'a) (*loc-33*)", "'a")) - /// let foo = () in let f (_ as $foo) = foo in () - [] - member public this.``GotoDefinition.Simple.Tricky.AsPatLHS`` () = - this.GotoDefinitionTestWithSimpleFile "foo) = (*loc-35*)" (Some("let f (_ as foo) = (*loc-35*)", "foo")) - /// let foo = () in let f (_ as #foo) = $foo in () - [] - member public this.``GotoDefinition.Simple.Tricky.AsPatRHS`` () = - this.GotoDefinitionTestWithSimpleFile "foo (*loc-36*)" (Some("let f (_ as foo) = (*loc-35*)", "foo")) - /// fun $x x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.LambdaMultBind1`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-37*)" (Some("fun x (*loc-37*)", "x")) - /// fun x $x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.LambdaMultBind2`` () = - this.GotoDefinitionTestWithSimpleFile "x -> (*loc-38*)" (Some("x -> (*loc-38*)", "x")) - /// fun x $x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.LambdaMultBindBody`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-39*)" (Some("x -> (*loc-38*)", "x")) - /// let f = () in let $f = function f -> f in () - [] - member public this.``GotoDefinition.Simple.Tricky.LotsOfFsFunc`` () = - this.GotoDefinitionTestWithSimpleFile "f = (*loc-41*)" (Some("let f = (*loc-41*)", "f")) - /// let f = () in let f = function $f -> f in () - [] - member public this.``GotoDefinition.Simple.Tricky.LotsOfFsPat`` () = - this.GotoDefinitionTestWithSimpleFile "f -> (*loc-42*)" (Some("function f -> (*loc-42*)", "f")) - /// let f = () in let f = function #f -> $f in () - [] - member public this.``GotoDefinition.Simple.Tricky.LotsOfFsUse`` () = - this.GotoDefinitionTestWithSimpleFile "f (*loc-43*)" (Some("function f -> (*loc-42*)", "f")) - /// let f x = match x with | Suc $x | x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.OrPatLeft`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-44*)" (Some("| Suc x (*loc-44*)", "x")) - /// let f x = match x with | Suc x | $x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.OrPatRight`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-45*)" (Some("| Suc x (*loc-44*)", "x")) // NOTE: or-patterns bind at first occurrence of the variable - /// let f x = match x with | Suc #y & z -> $y - [] - member public this.``GotoDefinition.Simple.Tricky.AndPat`` () = - this.GotoDefinitionTestWithSimpleFile "y (*loc-46*)" (Some("| Suc y & z -> (*loc-47*)", "y")) - /// let f xs = match xs with | #x :: xs -> $x - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPat`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-48*)" (Some("| x :: xs -> (*loc-49*)", "x")) - /// let f p = match p with (#y, z) -> $y - [] - member public this.``GotoDefinition.Simple.Tricky.PairPat`` () = - this.GotoDefinitionTestWithSimpleFile "y (*loc-50*)" (Some("| (y : int, z) -> (*loc-51*)", "y")) - /// fun xs -> match xs with x :: #xs when $xs <> [] -> x :: xs - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhen`` () = - this.GotoDefinitionTestWithSimpleFile "xs <> [] -> (*loc-52*)" (Some("| x :: xs (*loc-54*)", "xs")) - /// fun xs -> match xs with #x :: xs when xs <> [] -> $x :: xs - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhsX`` () = - this.GotoDefinitionTestWithSimpleFile "x :: xs (*loc-53*)" (Some("| x :: xs (*loc-54*)", "x")) - /// fun xs -> match xs with x :: #xs when xs <> [] -> x :: $xs - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhsXs`` () = - this.GotoDefinitionTestWithSimpleFile "xs (*loc-53*)" (Some("| x :: xs (*loc-54*)", "xs")) - /// let x = "$x" - [] - member public this.``GotoDefinition.Simple.Tricky.InStringFails`` () = - this.GotoDefinitionTestWithSimpleFile "x(*loc-72*)" None - /// let x = "hello - /// $x - /// " - [] - member public this.``GotoDefinition.Simple.Tricky.InMultiLineStringFails`` () = - this.GotoDefinitionTestWithSimpleFile "x(*loc-73*)" None - [] - member public this.``GotoDefinition.Simple.Tricky.QuotedKeyword`` () = - this.GotoDefinitionTestWithSimpleFile "let`` = (*loc-74*)" (Some("let rec ``let`` = (*loc-74*)", "``let``")) - /// module $Too = let foo = () - [] - member public this.``GotoDefinition.Simple.Module.DefModname`` () = - this.GotoDefinitionTestWithSimpleFile "Too = (*loc-55*)" (Some("module Too = (*loc-55*)", "Too")) - /// module Too = $foo = () - [] - member public this.``GotoDefinition.Simple.Module.DefMember`` () = - this.GotoDefinitionTestWithSimpleFile "foo = 0 (*loc-56*)" (Some("let foo = 0 (*loc-56*)", "foo")) - /// module #Too = foo = () - /// module Bar = open $Too - [] - member public this.``GotoDefinition.Simple.Module.Open`` () = - this.GotoDefinitionTestWithSimpleFile "Too (*loc-57*)" (Some("module Too = (*loc-55*)", "Too")) - /// module #Too = foo = () - /// $Too.foo - [] - member public this.``GotoDefinition.Simple.Module.QualifiedModule`` () = - this.GotoDefinitionTestWithSimpleFile "Too.foo (*loc-58*)" (Some("module Too = (*loc-55*)", "Too")) - /// module Too = #foo = () - /// Too.$foo - [] - member public this.``GotoDefinition.Simple.Module.QualifiedMember`` () = - this.GotoDefinitionTestWithSimpleFile "foo (*loc-58*)" (Some("let foo = 0 (*loc-56*)", "foo")) - /// type Parity = Even | Odd - /// let (|$Even|Odd|) x = if x % 0 = 0 then Even else Odd - [] - member public this.``GotoDefinition.Simple.ActivePat.ConsDefLHS`` () = - this.GotoDefinitionTestWithSimpleFile "Even|Odd|) x = (*loc-59*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - /// type Parity = Even | Odd - /// let (|#Even|Odd|) x = if x % 0 = 0 then $Even else Odd - [] - member public this.``GotoDefinition.Simple.ActivePat.ConsDefRhs`` () = - this.GotoDefinitionTestWithSimpleFile "Even (*loc-60*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - - /// type Parity = Even | Odd - /// let (|#Even|Odd|) x = if x % 0 = 0 then Even else Odd - /// let foo x = - /// match x with - /// | $Even -> 1 - /// | Odd -> 0 - [] - member public this.``GotoDefinition.Simple.ActivePat.PatUse`` () = - this.GotoDefinitionTestWithSimpleFile "Even -> 1 (*loc-61*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - /// let patval = (|Even|Odd|) (*loc-61b*) - [] - member public this.``GotoDefinition.Simple.ActivePat.PatUseValue`` () = - this.GotoDefinitionTestWithSimpleFile "en|Odd|) (*loc-61b*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - [] - member public this.``GotoDefinition.Library.InitialTest`` () = - this.GotoDefinitionTestWithLib "map (*loc-1*)" (Some("map", "lis.fs")) + // ********** Tests of OO Stuff ********** - /// type #Class$ () = - /// member c.Method () = () - [] - member public this.``GotoDefinition.ObjectOriented.ClassNameDef`` () = - this.GotoDefinitionTestWithSimpleFile " () = (*loc-62*)" (Some("type Class () = (*loc-62*)", "Class")) - /// type Class () = - /// member c.#Method$ () = () - [] - member public this.``GotoDefinition.ObjectOriented.ILMethodDef`` () = - this.GotoDefinitionTestWithSimpleFile " () = () (*loc-63*)" (Some("member c.Method () = () (*loc-63*)", "c.Method")) - /// type Class () = - /// member #c$.Method () = () - [] - member public this.``GotoDefinition.ObjectOriented.ThisDef`` () = - this.GotoDefinitionTestWithSimpleFile ".Method () = () (*loc-63*)" (Some("member c.Method () = () (*loc-63*)", "c")) - /// type Class () = - /// static member #Foo$ () = () - [] - member public this.``GotoDefinition.ObjectOriented.StaticMethodDef`` () = - this.GotoDefinitionTestWithSimpleFile " () = () (*loc-64*)" (Some("static member Foo () = () (*loc-64*)", "Foo")) - /// type #Class () = - /// member Method () = () - /// let c = Class$ () - [] - member public this.``GotoDefinition.ObjectOriented.ConstructorUse`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-65*)" (Some("type Class () = (*loc-62*)", "Class")) - /// type Class () = - /// member #Method () = () - /// let c = Class () - /// c.Method$ () - [] - member public this.``GotoDefinition.ObjectOriented.MethodInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-66*)" (Some("member c.Method () = () (*loc-63*)", "c.Method")) - /// type Class () = - /// static member #Foo () = () - /// Class.Foo$ () - [] - member public this.``GotoDefinition.ObjectOriented.StaticMethodInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-67*)" (Some("static member Foo () = () (*loc-64*)", "Foo")) - /// type Class () = - /// member c.Method# () = c.Method$ () - [] - member public this.``GotoDefinition.ObjectOriented.MethodSelfInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-68*)" (Some("member c.Method () = c.Method () (*loc-68*)", "c.Method")) - /// type Class () = - /// member c.Method1 () = c.Method2$ () - /// member #c.Method2 () = c.Method1 () - [] - member public this.``GotoDefinition.ObjectOriented.MethodToMethodForward`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-69*)" (Some("member c.Method2 () = c.Method1 () (*loc-70*)", "c.Method2")) - - /// type Class () = - /// member c.Method () = () - /// type Class' () = - /// member c.Method () = - /// let #c = Class () - /// c$.Method () - [] - member public this.``GotoDefinition.ObjectOriented.ShadowThis`` () = - this.GotoDefinitionTestWithSimpleFile ".Method () (*loc-71*)" (Some("let c = Class ()", "c")) - - /// type Class () = - /// member #c.Method () = () - /// type Class' () = - /// member c.Method () = - /// let c = Class () - /// c.Method$ () - [] - member public this.``GotoDefinition.ObjectOriented.ShadowThisMethodInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-71*)" (Some("member c.Method () = () (*loc-63*)", "c.Method")) - [] - member this.``GotoDefinition.ObjectOriented.StructConstructor`` () = - let lines = - [ - "" - "[]" - "type Astruct(x:int, y:int) =" - " []" - " val mutable a : int" - " new(a) = Astruct(a, a)" - "type AS = Astruct" - "let a1 = Astruct(0)" - "let b1 = Astruct(0, 1)" - "let c1 = Astruct()" - "let a2 = AS(0)" - "let b2 = AS(0, 1)" - "let c2 = AS()" - ] - - let (_,_, file) = this.CreateSingleFileProject(lines) - let checkGTD marker (line, col) = - MoveCursorToStartOfMarker (file, marker) - let res = GotoDefinitionAtCursor file |> fun x -> x.ToOption() |> Option.map (fun (res, _) -> res.iStartLine + 1, res.iStartIndex + 1) - AssertEqual(Some(line, col), res) - - checkGTD "Astruct(0)" (6, 3) - checkGTD "Astruct(0, 1)" (3, 6) - checkGTD "Astruct()" (3, 6) - checkGTD "AS(0)" (6, 3) - checkGTD "AS(0, 1)" (3, 6) - checkGTD "AS()" (3, 6) + + // ********** GetCompleteIdentifierIsland tests ********** @@ -1340,96 +484,20 @@ type UsingMSBuild() = | (None, Some _) -> Assert.Fail("Expected result, but didn't receive one!") - [] - member public this.``GetCompleteIdTest.TrivialBefore`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let $ThisIsAnIdentifier = ()" (Some "ThisIsAnIdentifier") - [] - member public this.``GetCompleteIdTest.TrivialMiddle`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let This$IsAnIdentifier = ()" (Some "ThisIsAnIdentifier") - [] - member public this.``GetCompleteIdTest.TrivialEnd`` () = - this.GetCompleteIdTest true "let ThisIsAnIdentifier$ = ()" (Some "ThisIsAnIdentifier") - this.GetCompleteIdTest false "let ThisIsAnIdentifier$ = ()" None - [] - member public this.``GetCompleteIdTest.GetsUpToDot1`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Te$st.Moo.Foo.bar" (Some "Test") - [] - member public this.``GetCompleteIdTest.GetsUpToDot2`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Test.Mo$o.Foo.bar" (Some "Test.Moo") - [] - member public this.``GetCompleteIdTest.GetsUpToDot3`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Test.Moo.Fo$o.bar" (Some "Test.Moo.Foo") - [] - member public this.``GetCompleteIdTest.GetsUpToDot4`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Test.Moo.Foo.ba$r" (Some "Test.Moo.Foo.bar") - [] - member public this.``GetCompleteIdTest.GetsUpToDot5`` () = - this.GetCompleteIdTest true "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" (Some "Test.Moo.Foo.bar") - this.GetCompleteIdTest false "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" None - [] - member public this.``GetCompleteIdTest.GetOperator`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = 3 +$ 4" None - [] - member public this.``Identifier.IsConstructor.Bug2516``() = - let fileContents = """ - module GotoDefinition - type One(*Mark1*) = One - let f (x : One(*Mark2*)) = 2""" - let definitionCode = "type One(*Mark1*) = One" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"(*Mark1*)",definitionCode) - [] - member public this.``Identifier.IsTypeName.Bug2516``() = - let fileContents = """ - module GotoDefinition - type One(*Mark1*) = One - let f (x : One(*Mark2*)) = 2""" - let definitionCode = "type One(*Mark1*) = One" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"(*Mark2*)",definitionCode) - [] - member public this.``ModuleName.OnDefinitionSite.Bug2517``() = - let fileContents = """ - namespace GotoDefinition - module Foo(*Mark*) = - let x = ()""" - let definitionCode = "module Foo(*Mark*) =" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"(*Mark*)",definitionCode) - - /// GotoDef on abbreviation - [] - member public this.``GotoDefinition.Abbreviation.Bug193064``() = - let fileContents = """ - type X = int - let f (x:X) = x(*Marker*) """ - let definitionCode = "let f (x:X) = x(*Marker*)" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"x(*Marker*)",definitionCode) - - /// Verify the GotoDefinition on UoM yield does NOT jump out error dialog, - /// will do nothing in automation lab machine or GTD SI.fs on dev machine with enlistment. - [] - member public this.``GotoDefinition.UnitOfMeasure.Bug193064``() = - let fileContents = """ - open Microsoft.FSharp.Data.UnitSystems.SI - UnitSymbols.A(*Marker*)""" - this.VerifyGoToDefnNoErrorDialogAtStartOfMarker(fileContents,"A(*Marker*)", "type A = ampere") + + // Context project system diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs index 110f8b9ac89..38f24f4ff4b 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs @@ -113,488 +113,7 @@ type UsingMSBuild() = let methodstr = methodstr.Value Assert.Equal(0, methodstr.GetParameterCount(expectedCount)) - [] - member public this.``Regression.OnConstructor.881644``() = - let fileContent = """new System.IO.StreamReader((*Mark*)""" - let methodstr = this.GetMethodListForAMethodTip(fileContent,"(*Mark*)") - Assert.True(methodstr.IsSome, "Expected a method group") - let methodstr = methodstr.Value - - if not (methodstr.GetDescription(0).Contains("#ctor")) then - failwith "Expected parameter info to contain #ctor" - - [] - member public this.``Regression.InsideWorkflow.6437``() = - let fileContent = """ - open System.IO - let computation2 = - async { use file = File.Open("",FileMode.Open) - let! buffer = file.AsyncRead((*Mark*)0) - return 0 }""" - let methodstr = this.GetMethodListForAMethodTip(fileContent,"(*Mark*)") - Assert.True(methodstr.IsSome, "Expected a method group") - let methodstr = methodstr.Value - - if not (methodstr.GetDescription(0).Contains("AsyncRead")) then - failwith "Expected parameter info to contain AsyncRead" - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_1``() = - let fileContent = """ - type T() = - member this.X - with set ((a:int), (b:int)) (c:int) = () - ((new T()).X((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": int") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_2``() = - let fileContent = """ - type IFoo = interface - abstract f : int -> int - end - let i : IFoo = null - i.f((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": int") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_3``() = - let fileContent = """ - type M() = - member this.f x = () - let m = new M() - m.f((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": unit") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_4``() = - let fileContent = """ - type T() = - member this.Foo(a,b) = "" - let t = new T() - t.Foo((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": string") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_5``() = - let fileContent = """ - let f x y = x + y - f((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": (int -> int) ") - - [] - member public this.``Regression.StaticVsInstance.Bug3626.Case1``() = - let fileContent = """ - type Foo() = - member this.Bar(instanceReturnsString:int) = "hllo" - static member Bar(staticReturnsInt:int) = 13 - let z = Foo.Bar((*Mark*))""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["staticReturnsInt"]]) - - [] - member public this.``Regression.StaticVsInstance.Bug3626.Case2``() = - let fileContent = """ - type Foo() = - member this.Bar(instanceReturnsString:int) = "hllo" - static member Bar(staticReturnsInt:int) = 13 - let Hoo = new Foo() - let y = Hoo.Bar((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["instanceReturnsString"]]) - - [] - member public this.``Regression.MethodInfo.Bug808310``() = - let fileContent = """System.Console.WriteLine((*Mark*)""" - let methodGroup = this.GetMethodListForAMethodTip(fileContent,"(*Mark*)") - Assert.True(methodGroup.IsSome, "Expected a method group") - let methodGroup = methodGroup.Value - - let description = methodGroup.GetDescription(0) - // Make sure that System.Console.WriteLine is not mentioned anywhere exception in the XML comment signature - let xmlCommentIndex = description.IndexOf("System.Console.WriteLine]") - let noBracket = description.IndexOf("System.Console.WriteLine") - Assert.True(noBracket>=0) - Assert.Equal(noBracket, xmlCommentIndex) - - [] - member public this.``NoArguments``() = - // we want to see e.g. - // g() : int - // and not - // g(unit) : int - let fileContents = """ - type T = - static member F() = 42 - static member G(x:unit) = 42 - - let r1 = T.F((*1*)) - let r2 = T.G((*2*)) - - let g() = 42 - let h((x:unit)) = 42 - let r3 = h((*3*)) - let r4 = g((*4*))""" - this.VerifyParameterCount(fileContents,"(*1*)", 0) - this.VerifyParameterCount(fileContents,"(*2*)", 0) - this.VerifyParameterCount(fileContents,"(*3*)", 0) - this.VerifyParameterCount(fileContents,"(*4*)", 0) - - [] - member public this.``Single.Constructor1``() = - let fileContent = """new System.DateTime((*Mark*)""" - this.VerifyHasParameterInfo(fileContent, "(*Mark*)") - - [] - member public this.``Single.Constructor2``() = - let fileContent = """ - open System - new DateTime((*Mark*)""" - this.VerifyHasParameterInfo(fileContent, "(*Mark*)") - - [] - member public this.``Single.DotNet.StaticMethod``() = - let code = [ "System.Object.ReferenceEquals(" ] - let (_, _, file) = this.CreateSingleFileProject(code) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"Object.ReferenceEquals(") - let methodGroup = GetParameterInfoAtCursor file - AssertMethodGroup(methodGroup, [["objA"; "objB"]]) - gpatcc.AssertExactly(0,0) - - [] - member public this.``Regression.NoParameterInfo.100I.Bug5038``() = - let fileContent = """100I((*Mark*)""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContent,"(*Mark*)") - - [] - member public this.``Single.DotNet.InstanceMethod``() = - let fileContent = """ - let s = "Hello" - s.Substring((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["startIndex"]; ["startIndex"; "length"]]) - - [] - member public this.``Single.BasicFSharpFunction``() = - let fileContent = """ - let foo(x) = 1 - foo((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["'a"]]) - - // [] disabled for F#8, legacy service, covered in FCS tests instead - member public this.``Single.DiscriminatedUnion.Construction``() = - let fileContent = """ - type MyDU = - | Case1 of int * string - | Case2 of V1 : int * string * V3 : bool - | Case3 of ``Long Name`` : int * Item2 : string - | Case4 of int - - let x1 = Case1((*Mark1*) - let x2 = Case2((*Mark2*) - let x3 = Case3((*Mark3*) - let x4 = Case4((*Mark4*) - """ - - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark1*)",[["int"; "string"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark2*)",[["V1: int"; "string"; "V3: bool"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark3*)",[["``Long Name`` : int"; "string"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark4*)",[["int"]]) - - // [] disabled for F#8, legacy service, covered in FCS tests instead - member public this.``Single.Exception.Construction``() = - let fileContent = """ - exception E1 of int * string - exception E2 of V1 : int * string * V3 : bool - exception E3 of ``Long Name`` : int * Data1 : string - - let x1 = E1((*Mark1*) - let x2 = E2((*Mark2*) - let x3 = E3((*Mark3*) - """ - - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark1*)",[["int"; "string"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark2*)",[["V1: int"; "string"; "V3: bool" ]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark3*)",[["``Long Name`` : int"; "string" ]]) - - [] - //This test verifies that ParamInfo on a provided type that exposes one (static) method that takes one argument works normally. - member public this.``TypeProvider.StaticMethodWithOneParam`` () = - let fileContent = """ - let foo = N1.T1.M1((*Marker*) - """ - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Marker*)",[["arg1"]], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a (static) method that takes >1 arguments works normally. - member public this.``TypeProvider.StaticMethodWithMoreParam`` () = - let fileContent = """ - let foo = N1.T1.M2((*Marker*) - """ - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Marker*)",[["arg1";"arg2"]], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case verify the TypeProvider static method return type or colon content of the method - //This test verifies that ParamInfo on a provided type that exposes one (static) method that takes one argument - //and returns something works correctly (more precisely, it checks that the return type is 'int') - member public this.``TypeProvider.StaticMethodColonContent`` () = - let fileContent = """ - let foo = N1.T1.M2((*Marker*) - """ - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Marker*)",": int", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - //This test verifies that ParamInfo on a provided type that exposes a Constructor that takes no argument works normally. - member public this.``TypeProvider.ConstructorWithNoParam`` () = - let fileContent = """ - let foo = new N1.T1((*Marker*) - """ - this.VerifyParameterInfoOverloadMethodIndex(fileContent,"(*Marker*)",0,[], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a Constructor that takes one argument works normally. - member public this.``TypeProvider.ConstructorWithOneParam`` () = - let fileContent = """ - let foo = new N1.T1((*Marker*) - """ - this.VerifyParameterInfoOverloadMethodIndex(fileContent,"(*Marker*)",1,["arg1"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a Constructor that takes >1 argument works normally. - member public this.``TypeProvider.ConstructorWithMoreParam`` () = - let fileContent = """ - let foo = new N1.T1((*Marker*) - """ - this.VerifyParameterInfoOverloadMethodIndex(fileContent,"(*Marker*)",2,["arg1";"arg2"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.WhenOpeningBracket`` () = - let fileContent = """ - type foo = N1.T<(*Marker*) - """ - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Marker*)",[["Param1";"ParamIgnored"]], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that after closing bracket ">" the ParamInfo isn't showing on a provided type that exposes a static parameter that takes >1 argument works normally. - //This is a regression test for Bug DevDiv:181000 - member public this.``TypeProvider.Type.AfterCloseBracket`` () = - let fileContent = """ - type foo = N1.T< "Hello", 2>(*Marker*) - """ - this.VerifyNoParameterInfoAtStartOfMarker(fileContent,"(*Marker*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo is showing after delimiter "," on a provided type that exposes a static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.AfterDelimiter`` () = - let fileContent = """ - type foo = N1.T<"Hello",(*Marker*) - """ - this.VerifyParameterInfoContainedAtStartOfMarker(fileContent,"(*Marker*)",["Param1";"ParamIgnored"], - [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - member public this.``Single.InMatchClause``() = - let v461 = Version(4,6,1) - let fileContent = """ - let rec f l = - match l with - | [] -> System.String.Format((*Mark*) - | x :: xs -> f xs""" - // Note, 3 of these 8 are only available on .NET 4.6.1. On .NET 4.5 only 5 overloads are returned. - let expected = [["format"; "arg0"]; //Net4.5 - ["format"; "args"]; //Net4.5 - ["provider"; "format"; "args"]; //Net4.5 - ["format"; "arg0"; "arg1"]; //Net4.5 - ["format"; "arg0"; "arg1"; "arg2"]; //Net4.5 - ["provider"; "format"; "arg0"]; //Net4.6.1 - ["provider"; "format"; "arg0"; "arg1"]; //Net4.6.1 - ["provider"; "format"; "arg0"; "arg1"; "arg2"]] //Net4.6.1 - - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)", expected) - - (* --- Parameter Info Systematic Tests ------------------------------------------------- *) - - member public this.TestSystematicParameterInfo (marker, methReq, ?startOfMarker) = - let code = - ["let arr = " - " seq { for c = 'a' to 'z' do yield c }" - " |> Seq.map ( fun c ->" - " async { let x = c.ToString() in" - " return System.String.Format(\"[{0}] for [{1}]\"(*loc-1*), x.ToUpperInvariant()(*loc-2*), c) })" - " |> Async.Parallel" - " |> Async.RunSynchronously" - - "let (alist: System.Collections.ArrayList) = System.Collections.ArrayList(2)" - "alist.[0] |> ignore" - "<@@ let x = 1 in x(*loc-8*) @@>" - - "type FunkyType =" - " private (*loc-4*)new() = {}" - " static member ConvertToInt32 (s : string) =" - " let mutable n = 0 in" - " let parseRes = System.Int32.TryParse(s, &n) in" - " if not parseRes then" - " raise (new System.ArgumentException(\"incorrect number format\"))" - " n" - - "type Fruit = | Apple | Banana" - "type KeyValuePair = { Key : int; Value : float }" - "let print (x : Fruit, kvp : KeyValuePair) = System.Console.WriteLine(x); System.Console.WriteLine(kvp)" - "print ((*loc-9*)Banana, {Key = 0; Value = 0.0})" - - "type Emp = " - " []" - " static val mutable private m_ID : int" - " static member private NextID () = Emp.m_ID <- Emp.m_ID + 1; Emp.m_ID" - " val mutable private m_EmpID : int" - " val mutable private m_Name : string" - " val mutable private m_Salary : float" - " val mutable private m_DoB : System.DateTime" - " (*loc-5*)" - - " // Overloaded Constructors" - " public new() =" - " { m_EmpID = Emp.NextID();" - " m_Name = System.String.Empty;" - " m_Salary = 0.0;" - " m_DoB = System.DateTime.Today }" - - " public new(name, salary, dob) as self = " - " new Emp() then" - " self.m_Name <- name" - " self.m_Salary <- salary" - " self.m_DoB <- dob" - - " public new(name, dob) =" - " new (*loc-3*)Emp(name, 0.0, dob)" - - " // Overloaded methods" - " member this.IncreaseBy(amount : float ) = this.m_Salary <- this.m_Salary + amount" - " member this.IncreaseBy(amount : int ) = this.IncreaseBy(float(amount))" - " member this.IncreaseBy(amount : float32) = this.IncreaseBy(float(amount))" - - "let ``Random Number Generator`` = System.Random()" - "let ``?Max!Value?`` = 100" - "let swap (a, b) = (b, a)" - - "[ \"Kevin\", System.DateTime.Today.AddYears(-25); \"John\", new System.DateTime(1980, 1, 1) ]" - "|> List.map ( fun a -> let pair = swap a in Emp(dob = fst pair, name = snd pair) )" - "|> List.iter ( fun a -> a.IncreaseBy(``Random Number Generator``.Next((*loc-7*)``?Max!Value?``)) )" - - "System.Console.ReadLine(" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - match startOfMarker with - | Some(start) when start = true - -> MoveCursorToStartOfMarker(file, marker) - | _ -> MoveCursorToEndOfMarker(file, marker) - - let methodGroup = GetParameterInfoAtCursor file - if (methReq = []) then - Assert.True(methodGroup.IsNone, "Expected no method group") - else - AssertMethodGroup(methodGroup, methReq) - // Test on .NET functions with no parameter - [] - member public this.``Single.DotNet.NoParameters`` () = - this.TestSystematicParameterInfo("x.ToUpperInvariant(", [ [] ]) - - // Test on .NET function with one parameter - [] - member public this.``Single.DotNet.OneParameter`` () = - this.TestSystematicParameterInfo("System.DateTime.Today.AddYears(", [ ["value: int"] ] ) - - // Test appearance of PI on second parameter of .NET function - [] - member public this.``Single.DotNet.OnSecondParameter`` () = - this.TestSystematicParameterInfo("loc-1*),", [ ["format"; "args"]; - ["format"; "arg0"]; - ["provider"; "format"; "args"]; - ["format"; "arg0"; "arg1"]; - ["format"; "arg0"; "arg1"; "arg2"] ] ) - // Test on .NET functions with parameter array - [] - member public this.``Single.DotNet.ParameterArray`` () = - this.TestSystematicParameterInfo("loc-2*),", [ ["format"; "args"]; - ["format"; "arg0"]; - ["provider"; "format"; "args"]; - ["format"; "arg0"; "arg1"]; - ["format"; "arg0"; "arg1"; "arg2"] ] ) - // Test on .NET indexers - [] - member public this.``Single.DotNet.IndexerParameter`` () = - this.TestSystematicParameterInfo("alist.[", [ ["index: int"] ] ) - - // Test on .NET parameters passed with 'out' keyword (byref) - [] - member public this.``Single.DotNet.ParameterByReference`` () = - this.TestSystematicParameterInfo("Int32.TryParse(s,", [ ["s: string"; "result: int byref"]; ["s"; "style"; "provider"; "result"] ] ) - - // Test on reference type and value type parameters (e.g. string & DateTime) - [] - member public this.``Single.DotNet.RefTypeValueType`` () = - this.TestSystematicParameterInfo("loc-3*)Emp(", [ []; - ["name: string"; "dob: System.DateTime"]; - ["name: string"; "salary: float"; "dob: System.DateTime"] ] ) - - // Test PI does not pop up at point of definition/declaration - [] - member public this.``Single.Locations.PointOfDefinition`` () = - this.TestSystematicParameterInfo("loc-4*)new(", [ ] ) - this.TestSystematicParameterInfo("member ConvertToInt32 (", [ ] ) - this.TestSystematicParameterInfo("member this.IncreaseBy(", [ ] ) - - // Test PI does not pop up on whitespace after type annotation - [] - member public this.``Single.Locations.AfterTypeAnnotation`` () = - this.TestSystematicParameterInfo("(*loc-5*)", [], true) - - - // Test PI does not pop up after non-parameterized properties - [] - member public this.``Single.Locations.AfterProperties`` () = - this.TestSystematicParameterInfo("System.DateTime.Today", []) - //this.TestSystematicParameterInfo("(*loc-8*)", [], true) - - // Test PI does not pop up after non-function values - [] - member public this.``Single.Locations.AfterValues`` () = - this.TestSystematicParameterInfo("(*loc-8*)", [], true) - - // Test PI does not pop up after non-parameterized properties and after values - [] - member public this.``Single.Locations.EndOfFile`` () = - this.TestSystematicParameterInfo("System.Console.ReadLine(", [ [] ]) - - // Test PI pop up on parameter list for attributes - [] - member public this.``Single.OnAttributes`` () = - this.TestSystematicParameterInfo("(*loc-6*)", [ []; [ "check: bool" ] ], true) - - // Test PI when quoted identifiers are used as parameter - [] - member public this.``Single.QuotedIdentifier`` () = - this.TestSystematicParameterInfo("(*loc-7*)", [ []; [ "maxValue" ]; [ "minValue"; "maxValue" ] ], true) - - // Test PI with parameters of custom type - [] - member public this.``Single.RecordAndUnionType`` () = - this.TestSystematicParameterInfo("(*loc-9*)", [ [ "Fruit"; "KeyValuePair" ] ], true) - - (* --- End Of Parameter Info Systematic Tests ------------------------------------------ *) - -(* Tests for Generic parameterinfos -------------------------------------------------------- *) - member private this.TestGenericParameterInfo (testLine, methReq) = let code = [ "open System"; "open System.Threading"; ""; testLine ] let (_, _, file) = this.CreateSingleFileProject(code) @@ -605,55 +124,6 @@ type UsingMSBuild() = else AssertMethodGroup(methodGroup, methReq) - [] - member public this.``Single.Generics.Typeof``() = - this.TestGenericParameterInfo("typeof(", []) - - [] - member public this.``Single.Generics.MathAbs``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Math.Abs(", sevenTimes ["value"]) - - [] - member public this.``Single.Generics.ExchangeInt``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Interlocked.Exchange(", sevenTimes ["location1"; "value"]) - - [] - member public this.``Single.Generics.Exchange``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Interlocked.Exchange(", sevenTimes ["location1"; "value"]) - - [] - member public this.``Single.Generics.ExchangeUnder``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Interlocked.Exchange<_> (", sevenTimes ["location1"; "value"]) - - [] - member public this.``Single.Generics.Dictionary``() = - this.TestGenericParameterInfo("System.Collections.Generic.Dictionary<_, option>(", [ []; ["capacity"]; ["comparer"]; ["capacity"; "comparer"]; ["dictionary"]; ["dictionary"; "comparer"] ]) - - [] - member public this.``Single.Generics.List``() = - this.TestGenericParameterInfo("new System.Collections.Generic.List< _ > ( ", [ []; ["capacity"]; ["collection"] ]) - - [] - member public this.``Single.Generics.ListInt``() = - this.TestGenericParameterInfo("System.Collections.Generic.List(", [ []; ["capacity"]; ["collection"] ]) - - [] - member public this.``Single.Generics.EventHandler``() = - this.TestGenericParameterInfo("new System.EventHandler( ", [ [""] ]) // function arg doesn't have a name - - [] - member public this.``Single.Generics.EventHandlerEventArgs``() = - this.TestGenericParameterInfo("System.EventHandler(", [ [""] ]) // function arg doesn't have a name - - [] - member public this.``Single.Generics.EventHandlerEventArgsNew``() = - this.TestGenericParameterInfo("new System.EventHandler ( ", [ [""] ]) // function arg doesn't have a name - - // Split into multiple lines using "\n" and find the index of "$" (and remove it from the text) member private this.ExtractLineInfo (line:string) = let idx, lines, foundDollar = line.Split([| '\r'; '\n' |], StringSplitOptions.RemoveEmptyEntries) |> List.ofArray |> List.foldBack (fun l (idx, lines, foundDollar) -> let i = l.IndexOf("$") @@ -700,141 +170,12 @@ type UsingMSBuild() = member public this.``Single.Locations.Simple``() = this.TestParameterInfoLocation("let a = System.Math.Sin($", 8) - [] - member public this.``Single.Locations.LineWithSpaces``() = - this.TestParameterInfoLocation("let r =\n"+ - " System.Math.Abs($0)", 3) // on the beginning of "System", not line! - - [] - member public this.``Single.Locations.FullCall``() = - this.TestParameterInfoLocation("System.Math.Abs($0)", 0) - - [] - member public this.``Single.Locations.SpacesAfterParen``() = - this.TestParameterInfoLocation("let a = Math.Sign( $-10 )", 8) - - [] - member public this.``Single.Locations.WithNamespace``() = - this.TestParameterInfoLocation("let a = System.Threading.Interlocked.Exchange($", 8) - - [] - member public this.``ParameterInfo.Locations.WithoutNamespace``() = - this.TestParameterInfoLocation("let a = Interlocked.Exchange($", 8) - - [] - member public this.``Single.Locations.WithGenericArgs``() = - this.TestParameterInfoLocation("Interlocked.Exchange($", 0) - - [] - member public this.``Single.Locations.FunctionWithSpace``() = - this.TestParameterInfoLocation("let a = sin 0$.0", 8) - - [] - member public this.``Single.Locations.MethodCallWithoutParens``() = - this.TestParameterInfoLocation("let n = Math.Sin 1$0.0", 8) - - [] - member public this.``Single.Locations.GenericCtorWithNamespace``() = - this.TestParameterInfoLocation("let _ = new System.Collections.Generic.Dictionary<_, _>($)", 12) // on the beginning of "System" (not on "new") - - [] - member public this.``Single.Locations.GenericCtor``() = - this.TestParameterInfoLocation("let _ = new Dictionary<_, _>($)", 12) // on the beginning of "System" (not on "new") - - [] //This test verifies that ParamInfo location on a provided type with namespace that exposes static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.ParameterInfoLocation.WithNamespace`` () = - this.TestParameterInfoLocation("type boo = N1.T<$",11, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] //This test verifies that ParamInfo location on a provided type without the namespace that exposes static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.ParameterInfoLocation.WithOutNamespace`` () = - this.TestParameterInfoLocation("open N1 \n"+"type boo = T<$", - expectedPos = 11, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] //This test verifies that no ParamInfo in a string for a provided type that exposes static parameter that takes >1 argument works normally. //The intent here to make sure the ParamInfo is not shown when inside a string - member public this.``TypeProvider.Type.Negative.InString`` () = - this.TestParameterInfoNegative("type boo = \"N1.T<$\"", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] //This test verifies that no ParamInfo in a Comment for a provided type that exposes static parameter that takes >1 argument works normally. //The intent here to make sure the ParamInfo is not shown when inside a comment - member public this.``TypeProvider.Type.Negative.InComment`` () = - this.TestParameterInfoNegative("// type boo = N1.T<$", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - // Following are tricky: - // if we can't find end of the identifier on the current line, - // we *must* look at the previous line to find the location where NameRes info ends - // so in these cases we can find the identifier and location of tooltip is beginning of it - // (but in general, we don't search for it) - [] - member public this.``Single.Locations.Multiline.IdentOnPrevLineWithGenerics``() = - this.TestParameterInfoLocation("let d = Dictionary<_, option< int >> \n" + - " ( $ )", 8) // on the "D" (line untestable) - - [] - member public this.``Single.Locations.Multiline.IdentOnPrevLine``() = - this.TestParameterInfoLocation("do Console.WriteLine\n" + - " ($\"Multiline\")", 3) - [] - member public this.``Single.Locations.Multiline.IdentOnPrevPrevLine``() = - this.TestParameterInfoLocation("do Console.WriteLine\n" + - " ( \n" + - " $ \"Multiline\")", 3) - - [] - member public this.``Single.Locations.GenericCtorWithoutNew``() = - this.TestParameterInfoLocation("let d = System.Collections.Generic.Dictionary<_, option< int >> ( $ )", 8) // on "S" - standard - - [] - member public this.``Single.Locations.Multiline.GenericTyargsOnTheSameLine``() = - this.TestParameterInfoLocation("let dict3 = System.Collections.Generic.Dictionary<_, \n" + - " option< int>>( $ )", 12) // on "S" (beginning of "System") - [] - member public this.``Single.Locations.Multiline.LongIdentSplit``() = - this.TestParameterInfoLocation("let ll = new System.Collections.\n" + - " Generic.List< _ > ($)", 13) // on "S" (beginning of "System") - - [] - member public this.``Single.Locations.OperatorTrick3``() = - this.TestParameterInfoLocation - ("let mutable n = null\n" + - "let aaa = Interlocked.Exchange(&n$, new obj())", 10) // "I" of Interlocked - - // A several cases that are tricky and we don't want to show anything - // in the following cases, we may return a location of an operator (its ambiguous), but we don't want to show info about it! - - [] - member public this.``Single.Negative.OperatorTrick1``() = - this.TestParameterInfoNegative - ("let fooo = 0\n" + - " >($ 1 )") // this may be end of a generic args specification - - [] - member public this.``Single.Negative.OperatorTrick2``() = - this.TestParameterInfoNegative - ("let fooo = 0\n" + - " <($ 1 )") - - /// No intellisense in comments/strings! - [] - member public this.``Single.InString``() = - this.TestParameterInfoNegative - ("let s = \"System.Console.WriteLine($)\"") - - /// No intellisense in comments/strings! - [] - member public this.``Single.InComment``() = - this.TestParameterInfoNegative - ("// System.Console.WriteLine($)") - [] member this.``Regression.LocationOfParams.AfterQuicklyTyping.Bug91373``() = let code = [ "let f x = x " @@ -909,28 +250,6 @@ We really need to rewrite some code paths here to use the real parse tree rather AssertEqual([|(1,14);(1,21);(1,21);(4,0)|], info.GetParameterLocations()) *) - [] - member public this.``ParameterInfo.NamesOfParams``() = - let testLines = [ - "type Foo =" - " static member F(a:int, b:bool, c:int, d:int, ?e:int) = ()" - "let a = 42" - "Foo.F(0,(a=42),d=3,?e=Some 4,c=2)" - "// names are _,_,d,e,c" ] - let (_, _, file) = this.CreateSingleFileProject(testLines) - MoveCursorToStartOfMarker(file, "0") - let info = GetParameterInfoAtCursor file - Assert.True(info.IsSome, "expected parameter info") - let info = info.Value - let names = info.GetParameterNames() - AssertEqual([| null; null; "d"; "e"; "c" |], names) - - // $ is the location of the cursor/caret - // ^ marks all of these expected points: - // - start of the long id that is the method call containing the caret - // - end of the long id that is the method call containing the caret - // - open paren of the method call (or first char of arg expression if no open paren) - // - for every param, end of expr that is the param (or closeparen if no params (unit)) member public this.TestParameterInfoLocationOfParams (testLine, ?markAtEOF, ?additionalReferenceAssemblies) = let cursorPrefix, testLines = this.ExtractLineInfo testLine let testLinesAndLocs = testLines |> List.mapi (fun i s -> @@ -977,305 +296,6 @@ We really need to rewrite some code paths here to use the real parse tree rather let info = GetParameterInfoAtCursor file Assert.True(info.IsNone, "expected no parameter info for this particular test, though it would be nice if this has started to work") - [] - member public this.``LocationOfParams.Case1``() = - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^(^"hel$lo"^)""") - - [] - member public this.``LocationOfParams.Case2``() = - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^ (^ "hel$lo {0}" ,^ "Brian" ^)""") - - [] - member public this.``LocationOfParams.Case3``() = - this.TestParameterInfoLocationOfParams( - """^System.Console.WriteLine^ - (^ - "hel$lo {0}" ,^ - "Brian" ^) """) - - [] - member public this.``LocationOfParams.Case4``() = - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^ (^ "hello {0}" ,^ ("tuples","don't $ confuse it") ^)""") - - [] - member public this.``ParameterInfo.LocationOfParams.Bug112688``() = - let testLines = [ - "let f x y = ()" - "module MailboxProcessorBasicTests =" - " do f 0" - " 0" - " let zz = 42" - " for timeout in [0; 10] do" - " ()" ] - let (_,_, file) = this.CreateSingleFileProject(testLines) - MoveCursorToStartOfMarker(file, "let zz") - // in the bug, this caused an assert to fire - let info = GetParameterInfoAtCursor file - () - - [] - member public this.``ParameterInfo.LocationOfParams.Bug112340``() = - let testLines = [ - """let a = typeof] - member public this.``Regression.LocationOfParams.Bug91479``() = - this.TestParameterInfoLocationOfParams("""let z = fun x -> x + ^System.Int16.Parse^(^$ """, markAtEOF=true) - - [] - member public this.``LocationOfParams.Attributes.Bug230393``() = - this.TestParameterInfoLocationOfParams(""" - let paramTest((strA : string),(strB : string)) = - strA + strB - ^paramTest^(^ $ - - [<^Measure>] - type RMB - """) - - [] - member public this.``LocationOfParams.InfixOperators.Case1``() = - // infix operators like '+' do not give their own param info - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^(^"" + "$"^)""") - - [] - member public this.``LocationOfParams.InfixOperators.Case2``() = - // infix operators like '+' do give param info when used as prefix ops - this.TestParameterInfoLocationOfParams("""System.Console.WriteLine((^+^)(^$3^)(4))""") - - [] - member public this.``LocationOfParams.GenericMethodExplicitTypeArgs()``() = - this.TestParameterInfoLocationOfParams(""" - type T<'a> = - static member M(x:int, y:string) = x + y.Length - let x = ^T.M^(^1,^ $"test"^) """) - - [] - member public this.``LocationOfParams.InsideAMemberOfAType``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.a = (1 <> ^System.Int32.Parse^(^"$"^)) """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case1``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = ^System.Int32.Parse^(^"$"^) - and set(z) = System.Int32.Parse("") |> ignore - member x.P2 with get() = System.Int32.Parse("") - member x.P2 with set(z) = System.Int32.Parse("") |> ignore """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case2``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = System.Int32.Parse("") - and set(z) = ^System.Int32.Parse^(^"$"^) |> ignore - member x.P2 with get() = System.Int32.Parse("") - member x.P2 with set(z) = System.Int32.Parse("") |> ignore """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case3``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = System.Int32.Parse("") - and set(z) = System.Int32.Parse("") |> ignore - member x.P2 with get() = ^System.Int32.Parse^(^"$"^) - member x.P2 with set(z) = System.Int32.Parse("") |> ignore """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case4``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = System.Int32.Parse("") - and set(z) = System.Int32.Parse("") |> ignore - member x.P2 with get() = System.Int32.Parse("") - member x.P2 with set(z) = ^System.Int32.Parse^(^"$"^) |> ignore """) - - [] - member public this.``LocationOfParams.InsideObjectExpression``() = - this.TestParameterInfoLocationOfParams(""" - let _ = { new ^System.Object^(^$^) with member _.GetHashCode() = 2}""") - - [] - member public this.``LocationOfParams.Nested1``() = - this.TestParameterInfoLocationOfParams("""System.Console.WriteLine("hello {0}" , ^sin^ (^4$2.0 ^) )""") - - - [] - member public this.``LocationOfParams.MatchGuard``() = - this.TestParameterInfoLocationOfParams("""match [1] with | [x] when ^box^(^$x^) <> null -> ()""") - - [] - member public this.``LocationOfParams.Nested2``() = - this.TestParameterInfoLocationOfParams("""System.Console.WriteLine("hello {0}" , ^sin^ 4^$2.0^ )""") - - [] - member public this.``LocationOfParams.Generics1``() = - this.TestParameterInfoLocationOfParams(""" - let f<'T,'U>(x:'T, y:'U) = (y,x) - let r = ^f^(^4$2,^""^)""") - - [] - member public this.``LocationOfParams.Generics2``() = - this.TestParameterInfoLocationOfParams("""let x = ^System.Collections.Generic.Dictionary^(^42,^n$ull^)""") - - [] - member public this.``LocationOfParams.Unions1``() = - this.TestParameterInfoLocationOfParams(""" - type MyDU = - | FOO of int * string - let r = ^FOO^(^42,^"$"^) """) - - [] - member public this.``LocationOfParams.EvenWhenOverloadResolutionFails.Case1``() = - this.TestParameterInfoLocationOfParams("""let a = new ^System.IO.FileStream^(^$^)""") - - [] - member public this.``LocationOfParams.EvenWhenOverloadResolutionFails.Case2``() = - this.TestParameterInfoLocationOfParams(""" - open System.Collections.Generic - open System.Linq - let l = List([||]) - ^l.Aggregate^(^$^) // was once a bug""") - - [] - member public this.``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case1``() = - // when only one 'statement' after the mismatched parens after a comma, the comma swallows it and it becomes a badly-indented - // continuation of the expression from the previous line - this.TestParameterInfoLocationOfParams(""" - type CC() = - member this.M(a,b,c,d) = a+b+c+d - let c = new CC() - ^c.M^(^1,^2,^3,^ $ - c.M(1,2,3,4)""", markAtEOF=true) - - [] - member public this.``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case2``() = - // when multiple 'statements' after the mismatched parens after a comma, the parser sees a single argument to the method that - // is a statement sequence, e.g. a bunch of discarded expressions. That is, - // c.M(1,2,3, - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // is like - // c.M(let r = 1,2,3, - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // in r) - this.TestParameterInfoLocationOfParams(""" - type CC() = - member this.M(a,b,c,d) = a+b+c+d - let c = new CC() - ^c.M^(^1,2,3, $ - c.M(1,2,3,4) - c.M(1,2,3,4) - c.M(1,2,3,4)""", markAtEOF=true) - - [] - member public this.``LocationOfParams.Tuples.Bug91360.Case1``() = - this.TestParameterInfoLocationOfParams(""" - ^System.Console.WriteLine^(^ (4$2,43) ^) // oops""") - - [] - member public this.``LocationOfParams.Tuples.Bug91360.Case2``() = - this.TestParameterInfoLocationOfParams(""" - ^System.Console.WriteLine^(^ $(42,43) ^) // oops""") - - [] - member public this.``LocationOfParams.Tuples.Bug123219``() = - this.TestParameterInfoLocationOfParams(""" - type Expr = | Num of int - type T<'a>() = - member this.M1(a:int*string, b:'a -> unit) = () - let x = new T() - - ^x.M1^(^(1,$ """, markAtEOF=true) - - [] - member public this.``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Open``() = - this.TestParameterInfoLocationOfParams(""" - let arr = Array.create 4 1 - arr.[1] <- ^System.Int32.Parse^(^$ - open^ System""") - - [] - member public this.``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Module``() = - this.TestParameterInfoLocationOfParams(""" - let arr = Array.create 4 1 - arr.[1] <- ^System.Int32.Parse^(^$ - ^module Foo = - let x = 42""") - - [] - member public this.``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Namespace``() = - this.TestParameterInfoLocationOfParams(""" - namespace Foo - module Bar = - let arr = Array.create 4 1 - arr.[1] <- ^System.Int32.Parse^(^$ - namespace^ Other""") - - [] - member this.``LocationOfParams.InheritsClause.Bug192134``() = - this.TestParameterInfoLocationOfParams(""" - type B(x : int) = - new(x1:int, x2: int) = new B(10) - type A() = - inherit ^B^(^1$,^2^)""") - - [] - member public this.``LocationOfParams.ThisOnceAsserted``() = - this.TestNoParameterInfo(""" - module CSVTypeProvider - - f(fun x -> - match args with - | [| y |] -> - for name, kind in (headerNames, - rowType.AddMember(new ^ProvidedProperty^(^$ - null - | _ -> failwith "unexpected generic params" ) - - let rec emitRegKeyNamedType (container:TypeContainer) (typeName:string) (key:RegistryKey) = - let keyType = 0 - keyType - - match types |> Array.tryFind (fun ty -> ty.Name = typeName^) with _ -> ()""") - - [] - member public this.``LocationOfParams.ThisOnceAssertedToo``() = - this.TestNoParameterInfo(""" - let readString() = - let x = 42 - while ('"' = '""' then - () - else - let sb = new System.Text.StringBuilder() - while true do - ($) """) - - [] - member public this.``LocationOfParams.UnmatchedParensBeforeModuleKeyword.Bug245850.Case2a``() = - this.TestParameterInfoLocationOfParams(""" - module Repro = - query { for a in ^System.Int16.TryParse^(^$ - ^module AA = - let x = 10 """) - - (* Tests for type provider static argument parameterinfos ------------------------------------------ *) - member public this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts (testLine:string, ?markAtEnd, ?additionalReferenceAssemblies) = let numSpacesOfIndent = let lines = testLine.Split[|'\n'|] @@ -1319,700 +339,3 @@ We really need to rewrite some code paths here to use the real parse tree rather printfn "%s" allText this.TestParameterInfoLocationOfParams (allText, markAtEOF=needMarkAtEnd, ?additionalReferenceAssemblies=additionalReferenceAssemblies) ) - - [] - member public this.``LocationOfParams.TypeProviders.Basic``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ 42 ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.BasicNamed``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored=42 ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - member public this.``LocationOfParams.TypeProviders.Prefix0``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ $ """, // missing all params, just have < - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix1``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ 42 """, // missing > - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix1Named``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored=42 """, // missing > - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix2``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ """, // missing last param - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix2Named1``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored= """, // missing last param after name with equals - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix2Named2``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored """, // missing last param after name sans equals - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Negative1``() = - this.TestNoParameterInfo(""" - type D = ^System.Collections.Generic.Dictionary^<^ in$t, int ^>""") - - [] - member public this.``LocationOfParams.TypeProviders.Negative2``() = - this.TestNoParameterInfo(""" - type D = ^System.Collections.Generic.List^<^ in$t ^>""") - - [] - member public this.``LocationOfParams.TypeProviders.Negative3``() = - this.TestNoParameterInfo(""" - let i = 42 - let b = ^i^<^ 4$2""") - - [] - member public this.``LocationOfParams.TypeProviders.Negative4.Bug181000``() = - this.TestNoParameterInfo(""" - type U = ^N1.T^<^ "foo",^ 42 ^>$ """, // when the caret is right of the '>', we should not report any param info - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.BasicWithinExpr``() = - this.TestNoParameterInfo(""" - let f() = - let r = id( ^N1.T^<^ "fo$o",^ ParamIgnored=42 ^> ) - r """, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.BasicWithinExpr.DoesNotInterfereWithOuterFunction``() = - this.TestParameterInfoLocationOfParams(""" - let f() = - let r = ^id^(^ N1.$T< "foo", ParamIgnored=42 > ^) - r """, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case1``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ 42,^ ,^ ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case2``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ,^ ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case3``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ ,^$ ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.StaticParametersAtConstructorCallSite``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - let x = new ^N1.T^<^ "fo$o",^ 42 ^>()""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``TypeProvider.FormatOfNamesOfSystemTypes``() = - let code = ["""type TTT = N1.T< "foo", ParamIgnored=42 > """] - let references = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - let (_, _, file) = this.CreateSingleFileProject(code, references = references) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"foo") - let methodGroup = GetParameterInfoAtCursor file - Assert.True(methodGroup.IsSome, "expected parameter info") - let methodGroup = methodGroup.Value - let actualDisplays = - [ for i = 0 to methodGroup.GetCount() - 1 do - yield [ for j = 0 to methodGroup.GetParameterCount(i) - 1 do - let (name,display,description) = methodGroup.GetParameterInfo(i,j) - yield display ] ] - let expected = [["Param1: string"; "ParamIgnored: int"]] // key here is we want e.g. "int" and not "System.Int32" - AssertEqual(expected, actualDisplays) - gpatcc.AssertExactly(0,0) - - [] - member public this.``ParameterNamesInFunctionsDefinedByLetBindings``() = - let useCases = - [ - """ - let foo (n1 : int) (n2 : int) = n1 + n2 - foo( - """, "foo(", ["n1: int"] - - """ - let foo (n1 : int, n2 : int) = n1 + n2 - foo( - """, "foo(", ["n1: int"; "n2: int"] - - """ - let foo (n1 : int, n2 : int) = n1 + n2 - foo(2, - """, "foo(2,", ["n1: int"; "n2: int"] - - (* Negative tests - display only types*) - """ - let foo = List.map - foo( - """, "foo(", ["'a -> 'b"] - - """ - let foo x = - let bar y = x + y - bar( - """, "bar(", ["int"] - - """ - let f (Some x) = x + 1 - f( - """, "f(", ["int option"] - ] - - for (code, marker, expectedParams) in useCases do - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, marker) - let methodGroup = GetParameterInfoAtCursor file - - Assert.True(methodGroup.IsSome, "expected parameter info") - let methodGroup = methodGroup.Value - - Assert.Equal(1, methodGroup.GetCount()) - - let expectedParamsCount = List.length expectedParams - Assert.Equal(expectedParamsCount, methodGroup.GetParameterCount(0)) - - let actualParams = [ for i = 0 to (expectedParamsCount - 1) do yield methodGroup.GetParameterInfo(0, i) ] - let ok = - actualParams - |> List.map (fun (_, d, _) -> d) - |> List.forall2 (=) expectedParams - if not ok then - printfn "==Parameters don't match==" - printfn "Expected parameters %A" expectedParams - printfn "Actual parameters %A" actualParams - failwith "Parameters don't match" - - (* Tests for multi-parameterinfos ------------------------------------------------------------------ *) - - [] - member public this.``ParameterInfo.ArgumentsWithParamsArrayAttribute``() = - let content = """let _ = System.String.Format("",(*MARK*))""" - let methodTip = this.GetMethodListForAMethodTip(content, "(*MARK*)") - Assert.True(methodTip.IsSome, "expected parameter info") - let methodTip = methodTip.Value - - let overloadWithTwoParamsOpt = - Seq.init (methodTip.GetCount()) (fun i -> - let count = methodTip.GetParameterCount(i) - let paramInfos = - [ - for c = 0 to (count - 1) do - let name = ref "" - let display = ref "" - let description = ref "" - methodTip.GetParameterInfo(i, c, name, display, description) - yield !name, !display,!description - ] - count, paramInfos - ) - |> Seq.tryFind(fun (i, _) -> i = 2) - match overloadWithTwoParamsOpt with - | Some(_, [_;(_name, display, _description)]) -> Assert.True(display.Contains("[] args")) - | x -> Assert.Fail(sprintf "Expected overload not found, current result %A" x) - - (* DotNet functions for multi-parameterinfo tests -------------------------------------------------- *) - [] - member public this.``Multi.DotNet.StaticMethod``() = - let fileContents = """System.Console.WriteLine("Today is {0:dd MMM yyyy}",(*Mark*)System.DateTime.Today)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"obj"]) - - [] - member public this.``Multi.DotNet.StaticMethod.WithinClassMember``() = - let fileContents = """ - type Widget(z) = - member x.a = (1 <> System.Int32.Parse("",(*Mark*) - - let widget = Widget(1) - 45""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"System.Globalization.NumberStyles"]) - - [] - member public this.``Multi.DotNet.StaticMethod.WithinLambda``() = - let fileContents = """let z = fun x -> x + System.Int16.Parse("",(*Mark*)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"System.Globalization.NumberStyles"]) - - [] - member public this.``Multi.DotNet.StaticMethod.WithinLambda2``() = - let fileContents = "let _ = fun file -> new System.IO.FileInfo((*Mark*)" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["string"]]) - - [] - member public this.``Multi.DotNet.InstanceMethod``() = - let fileContents = """ - let s = "Hello" - s.Substring(0,(*Mark*)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"int"]) - - (* Common functions for multi-parameterinfo tests -------------------------------------------------- *) - [] - member public this.``Multi.DotNet.Constructor``() = - let fileContents = "let _ = new System.DateTime(2010,12,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"int";"int"]) - - [] - member public this.``Multi.Constructor.WithinObjectExpression``() = - let fileContents = "let _ = { new System.Object((*Mark*)) with member _.GetHashCode() = 2}" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",[]) - - [] - member public this.``Multi.Function.InTheClassMember``() = - let fileContents = """ - type Foo() = - let foo1(a : int, b:int) = () - - member this.A() = - foo1(1,(*Mark*) - member this.A(a : string, b:int) = ()""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int"]]) - - [] - member public this.``Multi.ParamAsTupleType``() = - let fileContents = """ - let tuple((a : int, b : int), c : int) = a * b + c - let result = tuple((1, 2)(*Mark*), 3)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int * int";"int"]]) - - [] - member public this.``Multi.ParamAsCurryType``() = - let fileContents = """ - let multi (x : float) (y : float) = 0 - let sum(a, b) = a + b - let rtnValue = sum(multi (1.0(*Mark*)) 3.0, 5)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["float"]]) - - [] - member public this.``Multi.MethodInMatchCause``() = - let fileContents = """ - let rec f l = - match l with - | [] -> System.String.Format("{0:X2}",(*Mark*) - | x :: xs -> f xs""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"obj"]) - - [] - member public this.``Regression.Multi.IndexerProperty.Bug93945``() = - let fileContents = """ - type Year2(year : int) = - member this.Item (month : int, day : int) = - let monthIdx = - match month with - | _ when month > 12 -> failwithf "Invalid month [%d]" month - | _ when month < 1 -> failwithf "Invalid month [%d]" month - | _ -> month - let dateStr = sprintf "1-1-%d" year - DateTime.Parse(dateStr).AddMonths(monthIdx - 1).AddDays(float (day - 1)) - - let O'seven = new Year2(2007) - let randomDay = O'seven.[12,(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int"]]) - - [] - member public this.``Regression.Multi.ExplicitAnnotate.Bug93188``() = - let fileContents = """ - type LiveAnimalAttribute(a : int, b: string) = - inherit System.Attribute() - - [] - type Wombat() = class end""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"string"]]) - - [] - member public this.``Multi.Function.WithRecordType``() = - let fileContents = """ - type Vector = - { X : float; Y : float; Z : float } - let foo(x : int,v : Vector) = () - foo(12, { X = 10.0; Y = (*Mark*)20.0; Z = 30.0 })""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"Vector"]]) - - [] - member public this.``Multi.Function.AsParameter``() = - let fileContents = """ - let isLessThanZero x = (x < 0) - let containsNegativeNumbers intList = - let filteredList = List.filter isLessThanZero intList - if List.length filteredList > 0 - then Some(filteredList) - else None - let _ = Option.get(containsNegativeNumbers [6; 20; (*Mark*)8; 45; 5])""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int list"]]) - - [] - member public this.``Multi.Function.WithOptionType``() = - let fileContents = """ - let foo( a : int option, b : string ref) = 0 - let _ = foo(Some(12),(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int option";"string ref"]]) - - [] - member public this.``Multi.Function.WithOptionType2``() = - let fileContents = """ - let multi (x : float) (y : float) = x * y - let sum(a : int, b) = a + b - let options(a1 : int option, b1 : float option) = a1.ToString() + b1.ToString() - let rtnOption = options(Some(sum(1, 3)), (*Mark*)Some(multi 3.1 5.0)) """ - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int option";"float option"]]) - - [] - member public this.``Multi.Function.WithRefType``() = - let fileContents = """ - let foo( a : int ref, b : string ref) = 0 - let _ = foo(ref 12,(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int ref";"string ref"]]) - - (* Overload list/Adjust method's param for multi-parameterinfo tests ------------------------------ *) - - [] - member public this.``Multi.OverloadMethod.OrderedParameters``() = - let fileContents = "new System.DateTime(2000,12,(*Mark*)" - this.VerifyParameterInfoOverloadMethodIndex(fileContents,"(*Mark*)",3(*The fourth method*),["int";"int";"int"]) - - [] - member public this.``Multi.Overload.WithSameParameterCount``() = - let fileContents = """ - type Foo() = - member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () - member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () - let foo = new Foo() - foo.A1(1,1,(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int";"string";"bool"];["int";"string";"int";"bool"]]) - - [] - member public this.``ExtensionMethod.Overloads``() = - let fileContents = """ - module MyCode = - type A() = - member this.Method(a:string) = "" - module MyExtension = - type MyCode.A with - member this.Method(a:int) = "" - - open MyCode - open MyExtension - let foo = A() - foo.Method((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["string"];["int"]]) - - [] - member public this.``ExtensionProperty.Overloads``() = - let fileContents = """ - module MyCode = - type A() = - member this.Prop with get(a:string) = "" - module MyExtension = - type MyCode.A with - member this.Prop with get(a:int) = "" - - open MyCode - open MyExtension - let foo = A() - foo.Prop((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["string"];["int"]]) - - (* Generic functions for multi-parameterinfo tests ------------------------------------------------ *) - - [] - member public this.``Multi.Generic.ExchangeInt``() = - let fileContents = "System.Threading.Interlocked.Exchange(123,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["byref";"int"]) - - [] - member public this.``Multi.Generic.Exchange.``() = - let fileContents = "System.Threading.Interlocked.Exchange(12.0,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["byref";"float"]) - - [] - member public this.``Multi.Generic.ExchangeUnder``() = - let fileContents = "System.Threading.Interlocked.Exchange<_> (obj,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["byref";"obj"]) - - [] - member public this.``Multi.Generic.Dictionary``() = - let fileContents = "System.Collections.Generic.Dictionary<_, option>(12,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"System.Collections.Generic.IEqualityComparer"]) - - [] - member public this.``Multi.Generic.HashSet``() = - let fileContents = "System.Collections.Generic.HashSet({ 1 ..12 },(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["Seq<'a>";"System.Collections.Generic.IEqualityComparer<'a>"]) - - [] - member public this.``Multi.Generic.SortedList``() = - let fileContents = "System.Collections.Generic.SortedList<_,option> (12,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"System.Collections.Generic.IComparer<'TKey>"]) - - (* No Param Info Shown for multi-parameterinfo tests ---------------------------------------------- *) - - [] - member public this.``ParameterInfo.Multi.NoParameterInfo.InComments``() = - let fileContents = "//let _ = System.Object((*Mark*))" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.InComments2``() = - let fileContents = """(*System.Console.WriteLine((*Mark*)"Test on Fsharp style comments.")*)""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.OnFunctionDeclaration``() = - let fileContents = "let Foo(x : int, (*Mark*)b : string) = ()" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.WithinString``() = - let fileContents = """let s = "new System.DateTime(2000,12(*Mark*)" """ - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.OnProperty``() = - let fileContents = """ - let s = "Hello" - let _ = s.Length(*Mark*)""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.OnValues``() = - let fileContents = """ - type Foo = class - val private size : int - val private path : string - new (s : int, p : string) = {size = s; path(*Mark*) = p} - end""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - (* Regression tests/negative tests for multi-parameterinfos --------------------------------------- *) - // To be added when the bugs are fixed... - [] - //[] - member public this.``Regression.ParameterWithOperators.Bug90832``() = - let fileContents = """System.Console.WriteLine("This(*Mark*) is a" + " bug.")""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string"]) - - [] - member public this.``Regression.OptionalArguments.Bug4042``() = - let fileContents = """ - module ParameterInfo - type TT(x : int, ?y : int) = - let z = y - do printfn "%A" z - member this.Foo(?z : int) = z - - type TT2(x : int, y : int option) = - let z = y - do printfn "%A" z - let tt = TT((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int"]]) - - [] - //[] - member public this.``Regression.ParameterFirstTypeOpenParen.Bug90798``() = - let fileContents = """ - let a = async { - Async.AsBeginEnd((*Mark*) - } - let p = 10""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["'Arg -> Async<'T>"]]) - - [] - // regression test for bug 3878: no parameter info triggered by "(" - member public this.``Regression.NoParameterInfoTriggeredByOpenBrace.Bug3878``() = - let fileContents = """ - module ParameterInfo - let x = 1 + 2 - - let _ = System.Console.WriteLine ((*Mark*)) - - let y = 1""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",[""]) - - [] - // regression test for bug 4495 : Should alway sort method lists in order of argument count - member public this.``Regression.MethodSortedByArgumentCount.Bug4495.Case1``() = - let fileContents = """ - module ParameterInfo - - let a1 = System.Reflection.Assembly.Load("mscorlib") - let m = a1.GetType("System.Decimal").GetConstructor((*Mark*)null)""" - this.VerifyParameterInfoOverloadMethodIndex(fileContents,"(*Mark*)",0,["System.Type array"]) - - [] - member public this.``Regression.MethodSortedByArgumentCount.Bug4495.Case2``() = - let fileContents = """ - module ParameterInfo - - let a1 = System.Reflection.Assembly.Load("mscorlib") - let m = a1.GetType("System.Decimal").GetConstructor((*Mark*)null)""" - this.VerifyParameterInfoOverloadMethodIndex(fileContents,"(*Mark*)",1,["System.Reflection.BindingFlags"; - "System.Reflection.Binder"; - "System.Type array"; - "System.Reflection.ParameterModifier array"]) - - [] - member public this.``BasicBehavior.WithReference``() = - let fileContents = """ - open System.ServiceModel - let serviceHost = new ServiceHost((*Mark*))""" - let (solution, project, file) = this.CreateSingleFileProject(fileContents, references = ["System.ServiceModel"]) - - MoveCursorToStartOfMarker(file, "(*Mark*)") - TakeCoffeeBreak(this.VS) - let methodstr = GetParameterInfoAtCursor(file) - printfn "%A" methodstr - let expected = ["System.Type";"System.Uri []"] - AssertMethodGroupContain(methodstr,expected) - - [] - member public this.``BasicBehavior.CommonFunction``() = - let fileContents = """ - let f(x) = 1 - f((*Mark*))""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["'a"]]) - - [] - member public this.``BasicBehavior.DotNet.Static``() = - let fileContents = """System.String.Format((*Mark*)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"obj array"]) - -(*------------------------------------------IDE Query automation start -------------------------------------------------*) - [] - // ParamInfo works normally for calls as query operator arguments - // works fine In nested queries - member public this.``Query.InNestedQuery``() = - let fileContents = """ - let tuples = [ (1, 8, 9); (56, 45, 3)] - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let tp = (2,3,6) - let foo = - query { - for n in numbers do - yield (n, query {for x in tuples do - let r = x.Equals((*Marker1*)tp) - let _ = System.String.Format("",(*Marker2*)x) - select r }) - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker1*)",["obj"],queryAssemblyRefs) - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker2*)",["string";"obj array"],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - // ParamInfo Still works when an error exists - member public this.``Query.WithErrors``() = - let fileContents = """ - let tuples = [ (1, 8, 9); (56, 45, 3)] - let tp = (2,3,6) - let foo = - query { - for t in tuples do - orderBy (t.Equals((*Marker*)tp)) - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker*)",["obj"],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - member public this.``Query.OperatorWithParentheses``() = - let fileContents = """ - type Product() = - let mutable id = 0 - let mutable name = "" - - member x.ProductID with get() = id and set(v) = id <- v - member x.ProductName with get() = name and set(v) = name <- v - - let getProductList() = - [ - Product(ProductID = 1, ProductName = "Chai"); - Product(ProductID = 2, ProductName = "Chang"); ] - let products = getProductList() - let categories = ["Beverages"; "Condiments"; "Vegetables";] - // Group Join - let q2 = - query { - for c in categories do - groupJoin((*Marker1*)for p in products(*Marker2*) -> c = p.ProductName) into ps - select (c, ps) - } |> Seq.toArray""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker1*)",[],queryAssemblyRefs) - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker2*)",[],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - // ParamInfo Still works when there is an optional argument - member public this.``Query.OptionalArgumentsInQuery``() = - let fileContents = """ - type TT(x : int, ?y : int) = - let z = y - do printfn "%A" z - member this.Foo(?z : int) = z - - type TT2(x : int, y : int option) = - let z = y - do printfn "%A" z - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - let test3 = - query { - for n in numbers do - let tt = TT((*Marker*) - minBy n - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker*)",["int";"int"],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - // ParamInfo Still works when there are overload methods with the same param count - member public this.``Query.OverloadMethod.InQuery``() = - let fileContents = """ - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - type Foo() = - member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () - member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () - - let test3 = - query { - for n in numbers do - let foo = new Foo() - foo.A1(1,1,(*Marker*) - minBy n - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker*)",["int";"int";"string";"bool"],queryAssemblyRefs) - - -// Context project system -type UsingProjectSystem() = - inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs index bb9571afa67..ce47668a6fd 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs @@ -124,852 +124,45 @@ type UsingMSBuild() = let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" AssertContainsInOrder(tooltip, expectedExactOrder) - [] - member public this.``NestedTypesOrder``() = - this.VerifyOrderOfNestedTypesInQuickInfo( - source = "type t = System.Runtime.CompilerServices.RuntimeHelpers(*M*)", - marker = "(*M*)", - expectedExactOrder = ["GetHashCode"; "GetObjectValue"] - ) - [] - member public this.``Operators.TopLevel``() = - let source = """ - /// tooltip for operator - let (===) a b = a + b - let _ = "" === "" - """ - this.CheckTooltip( - code = source, - marker = "== \"\"", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.True(text.Contains "tooltip for operator")) - ) - [] - member public this.``Operators.Member``() = - let source = """ - type U = U - with - /// tooltip for operator - static member (+++) (U, U) = U - let _ = U +++ U - """ - this.CheckTooltip( - code = source, - marker = "++ U", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.True(text.Contains "tooltip for operator")) - ) - - [] - member public this.``QuickInfo.HiddenMember``() = - // Tooltips showed hidden members - #50 - let source = """ - open System.ComponentModel - - type TypeU = { Element : string } - with - [] - [] - member x._Print = x.Element.ToString() - - let u = { Element = "abc" } - """ - this.CheckTooltip( - code = source, - marker = "ypeU =", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.False(text.Contains "member _Print")) - ) - - [] - member public this.``QuickInfo.ObsoleteMember``() = - // Tooltips showed obsolete members - #50 - let source = """ - type TypeU = { Element : string } - with - [] - member x.Print1 = x.Element.ToString() - member x.Print2 = x.Element.ToString() - - let u = { Element = "abc" } - """ - this.CheckTooltip( - code = source, - marker = "ypeU =", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.False(text.Contains "member Print1")) - ) - - [] - member public this.``QuickInfo.HideBaseClassMembersTP``() = - let fileContents = "type foo = HiddenMembersInBaseClass.HiddenBaseMembersTP(*Marker*)" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "MembersTP(*Marker*)", - expected = "type HiddenBaseMembersTP =\n inherit TPBaseTy", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``QuickInfo.OverridenMethods``() = - let source = """ - type A() = - abstract member M: unit -> unit - /// 1234 - default this.M() = () - - type AA() = - inherit A() - /// 5678 - override this.M() = () - let x = new AA() - x.M() - - let y = new A() - y.M() - """ - for (marker, expected) in ["x.M", "5678"; "y.M", "1234"] do - this.CheckTooltip - ( - code = source, - marker = marker, - atStart = false, - f = (fun ((text : string, _), _) -> printfn "expected %s, actual %s" expected text; Assert.True (text.Contains(expected))) - ) - - [] - member public this.``QuickInfoForQuotedIdentifiers``() = - let source = """ - /// The fff function - let fff x = x - /// The gg gg function - let ``gg gg`` x = x - let r = fff 1 + ``gg gg`` 2 // no tip hovering over""" - let identifier = "``gg gg``" - for i = 1 to (identifier.Length - 1) do - let marker = "+ " + (identifier.Substring(0, i)) - this.CheckTooltip (source, marker, false, checkTooltip "gg gg") - [] - member public this.``QuickInfoSingleCharQuotedIdentifier``() = - let source = """ - let ``x`` = 10 - ``x``|> printfn "%A" - """ - this.CheckTooltip(source, "x``|>", true, checkTooltip "x") - - [] - member public this.QuickInfoForTypesWithHiddenRepresentation() = - let source = """ - let x = Async.AsBeginEnd - 1 - """ - let expectedTooltip = """ -type Async = - static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * objnull -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit) - static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate and 'Del: not null) - static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async - static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload - static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async - static member CancelDefaultToken: unit -> unit - static member Catch: computation: Async<'T> -> Async> - static member Choice: computations: Async<'T option> seq -> Async<'T option> - static member FromBeginEnd: beginAction: (AsyncCallback * objnull -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads - static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T> - ... -Full name: Microsoft.FSharp.Control.Async""".TrimStart().Replace("\r\n", "\n") - - this.CheckTooltip(source, "Asyn", false, checkTooltip expectedTooltip) - - [] - member public this.``TypeProviders.NestedTypesOrder``() = - let code = "type t = N1.TypeWithNestedTypes(*M*)" - let tpReference = PathRelativeToTestAssembly( @"DummyProviderForLanguageServiceTesting.dll") - this.VerifyOrderOfNestedTypesInQuickInfo( - source = code, - marker = "(*M*)", - expectedExactOrder = ["A"; "X"; "Z"], - extraRefs = [tpReference] - ) - - [] - member public this.``GetterSetterInsideInterfaceImpl.ThisOnceAsserted``() = - let fileContent =""" - type IFoo = - abstract member X: int with get,set - - type Bar = - interface IFoo with - member this.X - with get() = 42 // hello - and set(v) = id() """ - this.AssertQuickInfoContainsAtStartOfMarker(fileContent, "id", "Operators.id") - - //regression test for bug 3184 -- intellisense should normalize to ¡°int[]¡± so that [] is not mistaken for list. - [] - member public this.IntArrayQuickInfo() = - - let fileContents = """ - let x(*MIntArray1*) : int array = [| 1; 2; 3 |] - let y(*MInt[]*) : int [] = [| 1; 2; 3 |] - """ - this.AssertQuickInfoContainsAtStartOfMarker(fileContents, "x(*MIntArray1*)", "int array") - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "y(*MInt[]*)", "int array") - - //Verify no quickinfo -- link name string have - [] - member public this.LinkNameStringQuickInfo() = - - let fileContents = """ - let y = 1 - let f x = "x"(*Marker1*) - let g z = "y"(*Marker2*) - """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "\"x\"(*Marker1*)", "") - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "\"y\"(*Marker2*)", "") - - [] - //This is to test the correct TypeProvider Type message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Type.Comment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", "This is a synthetic type created by me!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.WithLongComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic type created by me!. Which is used to test the tool tip of the typeprovider type to check if it shows the right message or not.", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.WithNullComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "type T =\n new: unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.WithEmptyComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "type T =\n new : unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.LocalizedComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic type Localized! ኤፍ ሻርፕ", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test the correct TypeProvider Constructor message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Constructor.Comment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", "This is a synthetic .ctor created by me for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.WithLongComment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic .ctor created by me for N.T. Which is used to test the tool tip of the typeprovider Constructor to check if it shows the right message or not.", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.WithNullComment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "N.T() : N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.WithEmptyComment``() = - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "N.T() : N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.LocalizedComment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic .ctor Localized! ኤፍ ሻርፕ for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - - [] - //This is to test the correct TypeProvider event message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Event.Comment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "This is a synthetic *event* created by me for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.LocalizedComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "This is a synthetic *event* Localized! ኤፍ ሻርፕ for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.ParamsAttributeTest``() = - - let fileContents = """ - let t = "a".Split('c')""" - this.AssertQuickInfoContainsAtEndOfMarker (fileContents, "Spl", "[] separator") - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.WithLongComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "This is a synthetic *event* created by me for N.T. Which is used to test the tool tip of the typeprovider Event to check if it shows the right message or not.!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.WithNullComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "member N.T.Event1: IEvent", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.WithEmptyComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "member N.T.Event1: IEvent", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This is to test the correct TypeProvider Method message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Method.Comment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "This is a synthetic *method* created by me!!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.LocalizedComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "This is a synthetic *method* Localized! ኤፍ ሻርፕ", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.WithLongComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "This is a synthetic *method* created by me!!. Which is used to test the tool tip of the typeprovider Method to check if it shows the right message or not.!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.WithNullComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "N.T.M() : int array", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.WithEmptyComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "N.T.M() : int array", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This is to test the correct TypeProvider Property message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Property.Comment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "This is a synthetic *property* created by me for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.LocalizedComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "This is a synthetic *property* Localized! ኤፍ ሻርፕ for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.WithLongComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "This is a synthetic *property* created by me for N.T. Which is used to test the tool tip of the typeprovider Property to check if it shows the right message or not.!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.WithNullComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "property N.T.StaticProp: decimal", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.WithEmptyComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "property N.T.StaticProp: decimal", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This test case Verify that when Hover over foo the correct quickinfo is displayed for TypeProvider static parameter - //Dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - member public this.``TypeProvider.StaticParameters.Correct``() = - - let fileContents = """ - type foo(*Marker*) = N1.T< const "Hello World",2>""" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "foo(*Marker*)", - expected = "type foo = N1.T", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify that when Hover over foo the correct quickinfo is displayed - //Dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - //As you can see this is "Negative Case" to check that when given invalid static Parameter quickinfo shows "type foo = obj" - member public this.``TypeProvider.StaticParameters.Negative.Invalid``() = - - let fileContents = """ - type foo(*Marker*) = N1.T< const 100,2>""" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "foo(*Marker*)", - expected = "type foo", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify that when Hover over foo the XmlComment is shown in quickinfo - //Dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - member public this.``TypeProvider.StaticParameters.XmlComment``() = - - let fileContents = """ - ///XMLComment - type foo(*Marker*) = N1.T< const "Hello World",2>""" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "foo(*Marker*)", - expected = "XMLComment", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``TypeProvider.StaticParameters.QuickInfo.OnTheErasedType``() = - let fileContents = """type TTT = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)">""" - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "TTT", - expected = "type TTT = Samples.FSharp.RegexTypeProvider.RegexTyped<...>\nFull name: File1.TTT", - addtlRefAssy = ["System"; PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``TypeProvider.StaticParameters.QuickInfo.OnNestedErasedTypeProperty``() = - let fileContents = """ - type T = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)"> - let reg = T() - let r = reg.Match("425-123-2345").AreaCode.Value - """ - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "reaCode.Val", - expected = """property Samples.FSharp.RegexTypeProvider.RegexTyped<...>.MatchType.AreaCode: System.Text.RegularExpressions.Group""", - addtlRefAssy = ["System"; PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) // Regression for 2948 - [] - member public this.TypeRecordQuickInfo() = - - let fileContents = """namespace NS - type Re(*MarkerRecord*) = { X : int } """ - let expectedQuickinfoTypeRecord = "type Re = { X: int }" - - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Re(*MarkerRecord*)" expectedQuickinfoTypeRecord - [] - member public this.``QuickInfo.LetBindingsInTypes``() = - let code = - """ - type A() = - let fff n = n + 1 - """ - this.AssertQuickInfoContainsAtEndOfMarker(code, "let ff", "val fff: n: int -> int") // Regression for 2494 - [] - member public this.TypeConstructorQuickInfo() = - - let fileContents = """ - open System - - type PriorityQueue(*MarkerType*)<'k,'a> = - | Nil(*MarkerDataConstructor*) - | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a> - - module PriorityQueue(*MarkerModule*) = - let empty = Nil - - let minKeyValue = function - | Nil -> failwith "empty queue" - | Branch(k,a,_,_) -> (k,a) - - let minKey pq = fst (minKeyValue pq(*MarkerVal*)) - - let singleton(*MarkerLastLine*) k a = Branch(k,a,Nil,Nil) - """ - //Verify the quick info as expected - let expectedquickinfoPriorityQueue = "type PriorityQueue<'k,'a> = | Nil | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a>" - let expectedquickinfoNil = "union case PriorityQueue.Nil: PriorityQueue<'k,'a>" - let expectedquickinfoPriorityQueueinModule = "module PriorityQueue\n\nfrom File1" - let expectedquickinfoVal = "val pq: PriorityQueue<'a,'b>" - let expectedquickinfoLastLine = "val singleton: k: 'a -> a: 'b -> PriorityQueue<'a,'b>" - - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "PriorityQueue(*MarkerType*)" expectedquickinfoPriorityQueue - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Nil(*MarkerDataConstructor*)" expectedquickinfoNil - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "PriorityQueue(*MarkerModule*)" expectedquickinfoPriorityQueueinModule - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "pq(*MarkerVal*)" expectedquickinfoVal - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "singleton(*MarkerLastLine*)" expectedquickinfoLastLine - [] - member public this.NamedDUFieldQuickInfo() = - - let fileContents = """ - type NamedFieldDU(*MarkerType*) = - | Case1(*MarkerCase1*) of V1 : int * bool * V3 : float - | Case2(*MarkerCase2*) of ``Big Name`` : int * Item2 : bool - | Case3(*MarkerCase3*) of Item : int - - exception NamedExn(*MarkerException*) of int * V2 : string * bool * Data9 : float - """ - //Verify the quick info as expected - let expectedquickinfoType = "type NamedFieldDU = | Case1 of V1: int * bool * V3: float | Case2 of ``Big Name`` : int * bool | Case3 of int" - let expectedquickinfoCase1 = "union case NamedFieldDU.Case1: V1: int * bool * V3: float -> NamedFieldDU" - let expectedquickinfoCase2 = "union case NamedFieldDU.Case2: ``Big Name`` : int * bool -> NamedFieldDU" - let expectedquickinfoCase3 = "union case NamedFieldDU.Case3: int -> NamedFieldDU" - let expectedquickinfoException = "exception NamedExn of int * V2: string * bool * Data9: float" - - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "NamedFieldDU(*MarkerType*)" expectedquickinfoType - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Case1(*MarkerCase1*)" expectedquickinfoCase1 - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Case2(*MarkerCase2*)" expectedquickinfoCase2 - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Case3(*MarkerCase3*)" expectedquickinfoCase3 - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "NamedExn(*MarkerException*)" expectedquickinfoException - [] - member public this.``EnsureNoAssertFromBadParserRangeOnAttribute``() = - let fileContents = """ - [] - Types foo = int""" - this.AssertQuickInfoContainsAtEndOfMarker (fileContents, "ype", "") // just want to ensure there is no assertion fired by the parse tree walker - [] - member public this.``ActivePatterns.Declaration``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let ( |One|Two| ) x = One(x+1)""","ne|Tw","int -> Choice") - - [] - member public this.``ActivePatterns.Result``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let ( |One|Two| ) x = One(x+1)""","= On","active pattern result One: int -> Choice") - - - [] - member public this.``ActivePatterns.Value``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let ( |One|Two| ) x = One(x+1) - let patval = (|One|Two|) // use""","= (|On","int -> Choice") - - [] - member public this.``Regression.InDeclaration.Bug3176a``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type T<'a> = { aaaa : 'a; bbbb : int } ""","aa","aaaa") - - [] - member public this.``Regression.InDeclaration.Bug3176c``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type C = - val aaaa: int""","aa","aaaa") - - [] - member public this.``Regression.InDeclaration.Bug3176d``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type DU<'a> = - | DULabel of 'a""","DULab","DULabel") - - [] - member public this.``Regression.Generic.3773a``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let rec M2<'a>(a:'a) = M2(a)""","let rec M","val M2: a: 'a -> obj") - // Before this fix, if the user hovered over 'cccccc' they would see 'Yield' - [] - member public this.``Regression.ComputationExpressionMemberAppearingInQuickInfo``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """ - module Test - let q2 = - query { - for p in [1;2] do - join cccccc in [3;4] on (p = cccccc) - yield cccccc - }""" - "yield ccc" "Yield" - // Before this fix, if the user hovered over get or set in a property then - // they would see a quickinfo for any available function named get or set. - // The tests below define a get function with 'let' and then test to make sure that - // this isn't the get seen in the tool tip. - [] - member public this.``Regression.AccessorMutator.Bug4903a``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" - "with g" "string" - [] - member public this.``Regression.AccessorMutator.Bug4903d``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """namespace CountChocula - type BooBerry() = - member source.AMethod() = () - member source.AProperty - with get() : int = 0 - and set(value:int) : unit = ()""" - "AMetho" "string" - [] - member public this.``Regression.AccessorMutator.Bug4903b``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" - "and s" "seq" - - [] - member public this.``Regression.AccessorMutator.Bug4903c``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""", - "let g","string") - [] - member public this.``ParamsArrayArgument.OnType``() = - this.AssertQuickInfoContainsAtEndOfMarker - (""" - type A() = - static member Foo([] a : int[]) = () - let r = A.Foo(42)""" , - "type A","[] a:" ) - [] - member public this.``ParamsArrayArgument.OnMethod``() = - this.AssertQuickInfoContainsAtEndOfMarker - (""" - type A() = - static member Foo([] a : int[]) = () - let r = A.Foo(42)""" , - "A.Foo","[] a:" ) - [] - member public this.``Regression.AccessorMutator.Bug4903e``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" , - "member source.Pr","Prop" ) - [] - member public this.``Regression.AccessorMutator.Bug4903f``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" , - "member source.Pr","int" ) - [] - member public this.``Regression.AccessorMutator.Bug4903g``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" , - "member sou","source" ) - [] - member public this.``Regression.RecursiveDefinition.Generic.3773b``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let rec M1<'a>(a:'a) = M1(0)""","let rec M","val M1: a: int -> 'a") - //regression test for bug Dev11:138110 - "F# language service hover tip for ITypeProvider does now show Invalidate event" - [] - member public this.``Regression.ImportedEvent.138110``() = - let fileContents = """ -open Microsoft.FSharp.Core.CompilerServices -let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate - """ - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - "Provider(*$$$*)", - "Invalidate", addtlRefAssy=standard40AssemblyRefs ) //"FSharp.Core" add the reference in SxS will cause build failure and intellisense broken, the dll is added by default - [] - member public this.``Declaration.CyclicalDeclarationDoesNotCrash``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type (*1*)A = int * (*2*)A ""","(*2*)","type A") [] member public this.``JustAfterIdentifier``() = this.AssertQuickInfoContainsAtEndOfMarker ("""let f x = x + 1 ""","let f","int") - [] - member public this.``FrameworkClass``() = - let fileContent = """let l = new System.Collections.Generic.List()""" - let marker = "Generic.List" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"member Capacity: int\n") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"member Clear: unit -> unit\n") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "get_Capacity" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "set_Capacity" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "get_Count" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "set_Count" - [] - member public this.``FrameworkClassNoMethodImpl``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """let l = new System.Collections.Generic.LinkedList()""" - "Generic.LinkedList" "System.Collections.ICollection.ISynchronized" // Bug 5092: A framework class contained a private method impl // Disabled due to issue #11752 --- https://github.com/dotnet/fsharp/issues/11752 //[] @@ -1016,177 +209,16 @@ let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate (* ------------------------------------------------------------------------------------- *) - /// Even though we don't show squiggles, some types will still be known. For example, System.String. - [] - member public this.``OrphanFs.BaselineIntellisenseStillWorks``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let astring = "Hello" ""","let astr","string") - /// FEATURE: User may hover over a type or identifier and get basic information about it in a tooltip. - [] - member public this.``Basic``() = - let fileContent = """type (*bob*)Bob() = - let x = 1""" - let marker = "(*bob*)" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"Bob =") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"Bob =") - [] - member public this.``ModuleDefinition.ModuleNoNewLines``() = - let fileContent = """module XXX - type t = C3 - module YYY = - type t = C4 - ///Doc - module ZZZ = - type t = C5 """ - // The arises because the xml doc mechanism places these before handing them to VS for processing. - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"XX","module XXX") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"YY","module YYY\n\nfrom XXX") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"ZZ","module ZZZ\n\nfrom XXX\n\nDoc") - [] - member public this.``IdentifierWithTick``() = - let code = - [ - "let x = 1" - "let x' = \"foo\"" - "if (*aaa*)x = 1 then (*bbb*)x' else \"\"" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"(*aaa*)") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip,"val x: int") - MoveCursorToEndOfMarker(file,"(*bbb*)") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip,"val x': string") - [] - member public this.``NegativeTest.CharLiteralNotConfusedWithIdentifierWithTick``() = - let fileContent = """let x = 1" - let y = 'x' """ - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"'x","") // no tooltips for char literals - - [] - member public this.``QueryExpression.QuickInfoSmokeTest1``() = - let fileContent = """let q = query { for x in ["1"] do select x }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","custom operation: select", addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","custom operation: select ('Result)" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","Calls" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","Linq.QueryBuilder.Select" , addtlRefAssy=standard40AssemblyRefs ) - - [] - member public this.``QueryExpression.QuickInfoSmokeTest2``() = - let fileContent = """let q = query { for x in ["1"] do join y in ["2"] on (x = y); select (x,y) }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","custom operation: join" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","join var in collection on (outerKey = innerKey)" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","Calls" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","Linq.QueryBuilder.Join" , addtlRefAssy=standard40AssemblyRefs ) - - [] - member public this.``QueryExpression.QuickInfoSmokeTest3``() = - let fileContent = """let q = query { for x in ["1"] do groupJoin y in ["2"] on (x = y) into g; select (x,g) }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","custom operation: groupJoin" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","groupJoin var in collection on (outerKey = innerKey)" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","Calls" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","Linq.QueryBuilder.GroupJoin" , addtlRefAssy=standard40AssemblyRefs) - - - /// Hovering over a literal string should not show data tips for variable names that appear in the string - [] - member public this.``StringLiteralWithIdentifierLookALikes.Bug2360_A``() = - let fileContent = """let y = 1 - let f x = "x" - let g z = "y" """ - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "f x = \"" "val" - /// Hovering over a literal string should not show data tips for variable names that appear in the string - [] - member public this.``Regression.StringLiteralWithIdentifierLookALikes.Bug2360_B``() = - let fileContent = """let y = 1""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let ","int") - /// FEATURE: Intellisense information from types in earlier files in the project is available in subsequent files. - [] - member public this.``AcrossMultipleFiles``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - [ - "type Bob() = " - " let x = 1"]) - let file2 = AddFileFromText(project,"File2.fs", - [ "let bob = new File1.Bob()"]) - let file1 = OpenFile(project,"File1.fs") - let file2 = OpenFile(project,"File2.fs") - - // Get the tooltip at type Bob - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of first tooltip" - printf "First-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - - // Get the tooltip again - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of second tooltip" - printf "Second-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - /// FEATURE: Linked files work - [] - member public this.``AcrossLinkedFiles``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddLinkedFileFromTextEx(project, @"..\LINK.FS", @"..\link.fs", @"MyLink.fs", - [ - "type Bob() = " - " let x = 1"]) - let file2 = AddFileFromText(project,"File2.fs", - [ "let bob = new Link.Bob()"]) - let file1 = OpenFile(project, @"..\link.fs") - let file2 = OpenFile(project, @"File2.fs") - - // Get the tooltip at type Bob - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of first tooltip" - printf "First-%s\n" tooltip - AssertContains(tooltip,"Link.Bob") - - // Get the tooltip again - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of second tooltip" - printf "Second-%s\n" tooltip - AssertContains(tooltip,"Link.Bob") - [] - member public this.``TauStarter``() = - let code = - [ - "type (*Scenario01*)Bob() =" - " let x = 1" - "type (*Scenario021*)Bob =" - " class" - " public new() = { }" - "end" - "type (*Scenario022*)Alice =" - " class" - " public new() = { }" - "end"] - let (_, _, file) = this.CreateSingleFileProject(code) - TakeCoffeeBreak(this.VS) - MoveCursorToEndOfMarker(file,"(*Scenario021*)") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - printf "First-%s\n" tooltip - Assert.True(tooltip.Contains("Bob =")) - - MoveCursorToEndOfMarker(file,"(*Scenario022*)") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - printf "First-%s\n" tooltip - Assert.True(tooltip.Contains("Alice =")) member private this.QuickInfoResolutionTest lines queries = let code = [ yield! lines ] @@ -1233,385 +265,33 @@ let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate ("type Test0e = System.Collections.Generic.","KeyNotFoundException","Generic.KeyNotFoundException"); // note resolves to type ] - [] - member public this.``LongPaths``() = - let text,cases = this.GetLongPathsTestCases() - this.QuickInfoResolutionTest text cases - [] - member public this.``Global.LongPaths``() = - let text,cases = this.GetLongPathsTestCases() - let replace (s:string) = s.Replace("System", "global.System") - let text = text |> List.map (fun s -> replace s) - let cases = - cases - |> List.filter (fun (a,_,_) -> a.Contains "System") - |> List.map (fun (a,b,expectedResult) -> replace a, replace b, expectedResult) - - this.QuickInfoResolutionTest text cases - [] - member public this.``TypeAndModuleReferences``() = - this.QuickInfoResolutionTest - ["let test1 = List.length" - "let test2 = List.Empty" - "let test3 = (\"1\").Length" - "let test3b = (id \"1\").Length"] - - // The quick info specification // Some of the expected quick info text - [("let test1 = ","List" ,"module List"); - ("let test1 = List.","length" ,"length"); - ("let test2 = ","List" ,"Collections.List"); - ("let test2 = List.","Empty" ,"List.Empty"); - ("let test3 = (\"1\").","Length" ,"String.Length"); - ("let test3b = (id \"1\").","Length" ,"String.Length") ] - [] - member public this.``ModuleNameAndMisc``() = - this.QuickInfoResolutionTest - ["module (*test3q*)MM3 =" - " let y = 2" - "let test4 = lock"; - "let (*test5*) ffff xx = xx + 1" ] - - // The quick info specification // Some of the expected quick info text - [("module (*test3q*)","MM3" ,"module MM3"); - ("let test4 = ","lock" ,"lock"); - ("let (*test5*) ","ffff" ,"ffff") ] - [] - member public this.``MemberIdentifiers``() = - this.QuickInfoResolutionTest - ["type TestType() =" - " member (*test6*) xx.PPPP = 1" - " member (*test7*) xx.QQQQ(x) = 3.0" - "let test8 = (TestType()).PPPP"] - - // The quick info specification // Some of the expected quick info text - [("member (*test6*) ","xx" ,"TestType"); - ("member (*test6*) xx.","PPPP" ,"PPPP"); - ("member (*test7*) ","xx" ,"TestType"); - ("member (*test7*) xx.","QQQQ" ,"float"); - ("member (*test7*) xx.","QQQQ" ,"float"); - ("let test8 = (TestType()).", "PPPP" , "PPPP") ] - - [] - member public this.``IdentifiersForFields``() = - this.QuickInfoResolutionTest - ["type TestType9 = { XXX : int }" - "let test11 = { XXX = 1 }"] - - // The quick info specification // Some of the expected quick info text - [("type TestType9 = { ", "XXX" , "XXX: int"); - ("let test11 = { ", "XXX" , "XXX");] - [] - member public this.``IdentifiersForUnionCases``() = - this.QuickInfoResolutionTest - ["type TestType10 = Case1 | Case2 of int" - "let test12 = (Case1,Case2(3))"] - - // The quick info specification // Some of the expected quick info text - [("type TestType10 = ", "Case1" , "union case TestType10.Case1"); - ("type TestType10 = Case1 | ", "Case2" , "union case TestType10.Case2"); - ("let test12 = (", "Case1" , "union case TestType10.Case1"); - ("let test12 = (Case1,", "Case2" , "union case TestType10.Case2");] - [] - member public this.``IdentifiersInAttributes``() = - this.QuickInfoResolutionTest - ["[<(*test13*)System.CLSCompliant(true)>]" - "let test13 = 1" - "open System" - "[<(*test14*)CLSCompliant(true)>]" - "let test14 = 1"] - - // The quick info specification // Some of the expected quick info text - [("[<(*test13*)", "System" , "namespace System"); - ("[<(*test13*)System.", "CLSCompliant" , "CLSCompliantAttribute"); - ("[<(*test14*)", "CLSCompliant" , "CLSCompliantAttribute");] - [] - member public this.``ArgumentAndPropertyNames``() = - this.QuickInfoResolutionTest - ["type R = { mutable AAA : int }" - " static member M() = { AAA = 1 }" - "let test13 = R.M(AAA=3)" - "type R2() = " - " static member M() = System.Reflection.InterfaceMapping()" - "" - "let test14 = R2.M(InterfaceMethods= [| |])" - "" - "let test15 = new System.Reflection.AssemblyName(Name=\"Foo\")" - "let test16 = new System.Reflection.AssemblyName(assemblyName=\"Foo\")"] - - // The quick info specification // Some of the expected quick info text - [("let test13 = R.M(", "AAA" , "R.AAA: int"); - ("let test14 = R2.M(", "InterfaceMethods" , "field System.Reflection.InterfaceMapping.InterfaceMethods"); - ("let test15 = new System.Reflection.AssemblyName(", "Name" , "property System.Reflection.AssemblyName.Name"); - ("let test16 = new System.Reflection.AssemblyName(", "assemblyName", "argument assemblyName")] - /// Quickinfo was throwing an exception when the mouse was over the end of a line. - [] - member public this.``AtEndOfLine``() = - let fileContent = """//""" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "//" "Bug:" - [] - member public this.``Regression.FieldRepeatedInToolTip.Bug3538``() = - this.AssertIdentifierInToolTipExactlyOnce - """ - open System.Runtime.InteropServices - [] - type A() = - [] - val mutable x : int""" - "LayoutKind.Expl" "Explicit" - [] - member public this.``Regression.FieldRepeatedInToolTip.Bug3818``() = - this.AssertIdentifierInToolTipExactlyOnce - """ - [] - type A() = - do ()""" - "Inherite" "Inherited" // Get the tooltip at "Inherite" & Verify that it contains the 'Inherited' field exactly once - [] - member public this.``MethodAndPropTooltip``() = - let fileContent = """ - open System - do - Console.Clear() - Console.BackgroundColor |> ignore""" - this.AssertIdentifierInToolTipExactlyOnce fileContent "Console.Cle" "Clear" - this.AssertIdentifierInToolTipExactlyOnce fileContent "Console.Back" "BackgroundColor" - [] - member public this.``Regression.StaticVsInstance.Bug3626``() = - let fileContent = """ - type Foo() = - member this.Bar () = "hllo" - static member Bar() = 13 - let z = (*int*) Foo.Bar() - let Hoo = new Foo() - let y = (*string*) Hoo.Bar() """ - // Get the tooltip at "Foo.Bar(" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*int*) Foo.Ba","Foo.Bar") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*int*) Foo.Ba","-> int") - // Get the tooltip at "Hoo.Bar(" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*string*) Hoo.Ba","Foo.Bar") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*string*) Hoo.Ba","-> string") - - [] - member public this.``Class.OnlyClassInfo``() = - let fileContent = """type TT(x : int, ?y : int) = - class end""" - - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"type T","type TT") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "type T" "---" - - //KnownFail: [] - member public this.``Async.AsyncToolTips``() = - let fileContent = """let a = - async { - let ms = new System.IO.MemoryStream(Array.create 1000 1uy) - let toFill = Array.create 2000 0uy - let! x = ms.AsyncRead(2000) - return x - }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"asy","AsyncBuilder") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "asy" "---" - - [] - member public this.``Regression.Exceptions.Bug3723``() = - let fileContent = """exception E3E of int * int - exception E4E of (int * int) - exception E5E = E4E""" - // E3E should be un-parenthesized - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "exception E3" "(int * int)" - // E4E should be parenthesized - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"exception E4","(int * int)") - // E5E is an alias - should contain name of the aliased exception - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"exception E5","E4E") - [] - member public this.``Regression.Classes.Bug4066``() = - let fileContent = """type Foo() as this = - do this |> ignore - member this.Bar() = this""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"type Foo() as thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "type Foo() as thi" "ref" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"do thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "do thi" "ref" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"member thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "member thi" "ref" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"Bar() = thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "Bar() = thi" "ref" - [] - member public this.``Regression.Classes.Bug2362``() = - let fileContent = """let append mm nn = fun ac -> mm (nn ac)""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let appen","mm: ('a -> 'b) -> nn: ('c -> 'a) -> ac: 'c -> 'b") - // check consistency of QuickInfo for 'm' and 'n', which is the main point of this test - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let append m","'a -> 'b") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let append mm n","'c -> 'a") - [] - member public this.``Regression.ModuleAlias.Bug3790a``() = - let fileContent = """module ``Some`` = Microsoft.FSharp.Collections.List - module None = Microsoft.FSharp.Collections.List""" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "module ``So" "Option" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "module No" "Option" - [] - member public this.``Regression.ModuleAlias.Bug3790b``() = - let code = - [ - "module ``Some`` = Microsoft.FSharp.Collections.List" - "let _ = ``Some``.append [] []" ] - let (_, _, file) = this.CreateSingleFileProject(code) - - // Test quickinfo in place where the declaration is used - MoveCursorToEndOfMarker(file, "= ``So") - let tooltip = GetQuickInfoAtCursor file - AssertNotContains(tooltip, "Option") - [] - member public this.``Regression.ActivePatterns.Bug4100a``() = - let fileContent = """let (|Lazy|) x = x - match 0 with | Lazy y -> ()""" - // Test quickinfo in place where the declaration is used - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "with | Laz" "'?" // e.g. "Lazy: '?3107 -> '?3107", "Lazy: 'a -> 'a" will be fine - - [] - member public this.``Regression.ActivePatterns.Bug4100b``() = - let fileContent = """let Some (a:int) = a - match None with - | Some _ -> () - | _ -> () - - let (|NSome|) (a:int) = a - let NSome (a:int) = a.ToString() - match 0 with - | NSome _ -> ()""" - // This shouldn't be the local function - it should find the 'Some' union case - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "| Som" "int -> int" - // This shouldn't find the function returning string but a pattern returning int - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "| NSom" "int -> string" - - [] - member public this.``Regression.ActivePatterns.Bug4103``() = - let fileContent = """let (|Lazy|) x = x - match 0 with | Lazy y -> ()""" - // Test quickinfo in place where the declaration is used - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "(|Laz" "Control.Lazy" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(|Laz","|Lazy|") - - // This test checks that we don't show any tooltips for operators - // (which is currently not supported, but it used to collide with support for active patterns) - [] - member public this.``Regression.NoTooltipForOperators.Bug4567``() = - let fileContent = """let ( |+| ) a b = a + b - let n = 1 |+| 2 - let b = true || false - ()""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"( |+","") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"1 |+","") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"true |","") // Check to see that two distinct projects can be present - [] - member public this.``AcrossTwoProjects``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project1 = CreateProject(solution,"testproject1") - let file1 = AddFileFromText(project1,"File1.fs", - [ - "type (*bob*)Bob1() = " - " let x = 1"]) - let file1 = OpenFile(project1,"File1.fs") - let project2 = CreateProject(solution,"testproject2") - let file2 = AddFileFromText(project2,"File2.fs", - [ - "type (*bob*)Bob2() = " - " let x = 1"]) - let file2 = OpenFile(project2,"File2.fs") - - // Check Bob1 - MoveCursorToEndOfMarker(file1,"type (*bob*)Bob") - let tooltip = time1 GetQuickInfoAtCursor file1 "Time of file1 tooltip" - printf "Tooltip for file1:\n%s\n" tooltip - Assert.True(tooltip.Contains("Bob1 =")) - - // Check Bob2 - MoveCursorToEndOfMarker(file2,"type (*bob*)Bob") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of file2 tooltip" - printf "Tooltip for file2:\n%s\n" tooltip - Assert.True(tooltip.Contains("Bob2 =")) // In this bug, relative paths with .. in them weren't working. - [] - member public this.``BugInRelativePaths``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - [ - "type Bob() = " - " let x = 1"]) - let file2 = AddFileFromText(project,"..\\File2.fs", - [ - "let bob = new File1.Bob()"]) - let file1 = OpenFile(project,"File1.fs") - let file2 = OpenFile(project,"..\\File2.fs") - - // Get the tooltip at type Bob - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of first tooltip" - printf "First-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - - // Get the tooltip again - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of second tooltip" - printf "Second-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - // QuickInfo over a type that references types in an unreferenced assembly works. - [] - member public this.``MissingDependencyReferences.QuickInfo.Bug5409``() = - let code = - [ - "let myForm = new System.Windows.Forms.Form()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Windows.Forms"]) - MoveCursorToEndOfMarker(file,"myFo") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - printf "First-%s\n" tooltip -// ShowErrors(project) - AssertContains(tooltip,"Form") - - /// In this bug, the EOF token was reached before the parser could close the (, with, and let - /// The fix--at the point in time it was fixed--was to modify the parser to send a limited number - /// of additional EOF tokens to allow the recovery code to proceed up the change of productions - /// in the grammar. - [] - member public this.``Regression.Bug1605``() = - let fileContent = """let rec f l = - match l with - | [] -> string.Format( - | x::xs -> "hello" """ - // This string doesn't matter except that it should prove there is some datatip present. - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"| [] -> str","string") + - [] - member public this.``Regression.Bug4642``() = - let fileContent = """ "AA".Chars """ - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"\"AA\".Ch","int -> char") /// Complete a member completion and confirm that its data tip contains the fragments /// in rhsContainsOrder @@ -1629,319 +309,19 @@ let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate ShowErrors(project) failwith $"Could not find completion name '{completionName}'" - [] - //``CompletiongListItem.DocCommentsOnMembers`` and with //Regression 5856 - member public this.``Regression.MemberDefinition.DocComments.Bug5856_1``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type MyType = " - " /// Hello" - " static member Overload() = 0" - " /// Hello2" - " static member Overload(x:int) = 0" - " /// Hello3" - " static member NonOverload() = 0" - "MyType." - ] , - (* marker *) - "MyType.", - (* completed item *) - "Overload", - (* expect to see in order... *) - [ - "static member MyType.Overload: unit -> int"; - "static member MyType.Overload: x: int -> int"; - "Hello" - ] - ) - - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_2``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Outer =" - " /// Comment" - " module Inner =" - " let x = 1" - "let x() = " - " Outer." - ] , - (* marker *) - "Outer.", - (* completed item *) - "Inner", - (* expect to see in order... *) - [ - "module Inner"; - "from"; "Outer"; - "Comment" - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_3``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// Union comment" - " type Union =" - " /// Case comment" - " | Case of int" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Case", - (* expect to see in order... *) - [ - "union case Module.Union.Case: int -> Module.Union"; - "Case comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_4``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// Union comment" - " type Union =" - " /// Case comment" - " | Case of int" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Union", - (* expect to see in order... *) - [ - "type Union ="; - " | Case of int"; - //"Full name:"; "Module.Union"; - "Union comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_5``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// Pattern comment" - " let (|Pattern|) = 0" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Pattern", - (* expect to see in order... *) - [ - "active recognizer Pattern: int"; - //"Full name:"; "Module"; "|Pattern|"; - "Pattern comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_6``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// A comment" - " exception MyException of int" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "MyException", - (* expect to see in order... *) - [ - "exception MyException of int"; - //"Full name:"; "Module"; "MyException"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_7``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type Record = {" - " /// A comment" - " field : int" - " }" - "let record = {field = 1}" - "let x() =" - " record." - ] , - (* marker *) - "record.", - (* completed item *) - "field", - (* expect to see in order... *) - [ - "Record.field: int"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_8``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type Foo =" - " /// A comment" - " static member Property" - " with get() = \"\"" - "let x() = " - " Foo." - ] , - (* marker *) - "Foo.", - (* completed item *) - "Property", - (* expect to see in order... *) - [ - "property Foo.Property: string"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_9``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// A comment" - " type Class = class end" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Class", - (* expect to see in order... *) - [ - "type Class"; - //"Full name:"; "Module"; "Class"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_10``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System.String." - ] , - (* marker *) - "String.", - (* completed item *) - "Format", - (* expect to see in order... *) - [ - "System.String.Format("; - "[Filename:"; "mscorlib.dll]"; - "[Signature:M:System.String.Format(System.String,System.Object[])]"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_13``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System.Collections.Generic.Dictionary." - ] , - (* marker *) - "Dictionary.", - (* completed item *) - "KeyCollection", - (* expect to see in order... *) - [ - "type KeyCollection<"; - "member CopyTo"; - """Represents the collection of keys in a . This class cannot be inherited.""" - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_14``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System." - ] , - (* marker *) - "System.", - (* completed item *) - "ArgumentException", - (* expect to see in order... *) - [ - "type ArgumentException"; - "member Message"; - "The exception that is thrown when one of the arguments provided to a method is not valid.] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_15``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System.AppDomain." - ] , - (* marker *) - "AppDomain.", - (* completed item *) - "CurrentDomain", - (* expect to see in order... *) - [ - "property System.AppDomain.CurrentDomain: System.AppDomain"; - """Gets the current application domain for the current .""" - ] - ) - [] - member public this.``Regression.ExtensionMethods.DocComments.Bug6028``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - @"open System.Linq -let rec query:System.Linq.IQueryable<_> = null -query." - ] , - (* marker *) - "query.", - (* completed item *) - "All", - (* expect to see in order... *) - [ - "IQueryable.All"; - "[Filename"; "System.Core.dll]"; - "[Signature:M:System.Linq.Enumerable.All``1" - ] - ) [] member public this.``Regression.OnMscorlibMethodInScript.Bug6489``() = @@ -1964,850 +344,35 @@ query." ) - /// BUG: intellisense on "self" parameter in implicit ctor classes is wrong - [] - member public this.``Regression.CompListItemInfo.Bug5694``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type Form2() as self =" - " inherit System.Windows.Forms.Form()" - " let f() = self." - ] , - (* marker *) - "self.", - (* completed item *) - "AcceptButton", - (* expect to see in order... *) - [ - "Gets or sets the button on the form that is clicked when the user presses the ENTER key." - ] - ) - - - /// Bug 4592: Check that ctors are displayed from C# classes, i.e. the "new" lines below. - [] - member public this.``Regression.Class.Printing.CSharp.Classes.Only.Bug4592``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["System.Random"] , - (* marker *) - "System.Random", - (* completed item *) - "Random", - (* expect to see in order... *) - ["type Random ="; - " new: unit -> unit + 1 overload" - " member Next: unit -> int + 2 overloads"; - " member NextBytes: buffer: byte array -> unit"; - " member NextDouble: unit -> float"] - ) - - [] - member public this.``GenericDotNetMethodShowsComment``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["System.Linq.ParallelEnumerable."] , - (* marker *) - "ParallelEnumerable.", - (* completed item *) - "ElementAt", - (* expect to see in order... *) - [ - "Signature:M:System.Linq.ParallelEnumerable.ElementAt``1(System.Linq.ParallelQuery{``0},System.Int32" - ] - ) - - /// Bug 4624: Check the order in which members are printed, C# classes - [] - member public this.``Regression.Class.Printing.CSharp.Classes.Bug4624``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["System.Security.Policy.CodeConnectAccess"], - (* marker *) - "System.Security.Policy.CodeConnectAccess", - (* completed item *) - "CodeConnectAccess", - (* expect to see in order... *) - // Pre fix output is mixed up - [ "type CodeConnectAccess ="; - " new: allowScheme: string * allowPort: int -> unit"; - " member Equals: o: obj -> bool"; - " member GetHashCode: unit -> int"; - " static member CreateAnySchemeAccess: allowPort: int -> CodeConnectAccess"; - " static member CreateOriginSchemeAccess: allowPort: int -> CodeConnectAccess"; - " static val AnyScheme: string"; - " static val DefaultPort: int"; - " ..."; - ]) - - /// Bug 4624: Check the order in which members are printed, F# classes - [] - member public this.``Regression.Class.Printing.FSharp.Classes.Bug4624``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["type F1() = "; - " class "; - " inherit System.Windows.Forms.Form()"; - " abstract AAA : int with get"; - " abstract ZZZ : int with get"; - " abstract AAA : bool with set"; - " val x : F1"; - " static val x : F1"; - " static member A() = 12"; - " member this.B() = 12"; - " static member C() = 12"; - " member this.D() = 12"; - " member this.D with get() = 12 and set(12) = ()"; - " member this.D(x:int,y:int) = 12"; - " member this.D(x:int) = 12"; - " member this.D x y z = [1;x;y;z]"; - " override this.ToString() = \"\""; - " interface System.IDisposable with"; - " override this.Dispose() = () "; - " end"; - " end"; - "type A1 = F1"], - (* marker *) - "type A1 = F1", - (* completed item *) - "F1", - (* expect to see in order... *) - // Pre fix output is mixed up - [ "type F1 ="; - " inherit Form"; - " interface IDisposable"; - " new: unit -> F1"; - " val x: F1" - " member B: unit -> int"; - " override ToString: unit -> string"; - " static member A: unit -> int"; - " static member C: unit -> int"; - " abstract AAA: int"; - " member D: int"; - " ..."; - ]) -(*------------------------------------------IDE automation starts here -------------------------------------------------*) - [] - member public this.``Automation.Regression.AccessibilityOnTypeMembers.Bug4168``() = - let fileContent = """module Test - type internal Foo2(*Marker*) () = - member public this.Prop1 = 12 - member internal this.Prop2 = 12 - member private this.Prop3 = 12 - public new(x:int) = new Foo2() - internal new(x:int,y:int) = new Foo2() - private new(x:int,y:int,z:int) = new Foo2()""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "type internal Foo2") - [] - member public this.``Automation.Regression.AccessorsAndMutators.Bug4276``() = - let fileContent = """type TestType1(*Marker1*)( x : int , y : int ) = - let mutable x = x - let mutable y = y - - // Property with getter and setter - member this.X with get () = x - and set x' = x <- x' - - // Property with setter only - member this.Y with set y' = y <- y' - - // Property with getter only - member this.Length with get () = sqrt(float (x * x + y * y)) - - member this.Item with get (i : int) = match i with | 0 -> x | 1 -> y | _ -> failwith "Incorrect index" - - let point = TestType1(10,10) - - point.X <- 3 - point.Y <- 4 - - let x = point.[0] - let y = point.[1] - - let bitArray = new System.Collections.BitArray(*Marker2*)(1) - - point.Length |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "type TestType1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member Length: float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member Item") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member X: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member Y: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "type BitArray") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "member Not: unit -> BitArray") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker2*)" "get_Length" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker2*)" "set_Length" - - [] - member public this.``Automation.AutoOpenMyNamespace``() = - let fileContent ="""namespace System.Numerics - type t = BigInteger(*Marker1*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "r(*Marker1*)", "type BigInteger") - [] - member public this.``Automation.Regression.BeforeAndAfterIdentifier.Bug4371``() = - let fileContent = """module Test - let f arg1 (arg2, arg3, arg4) arg5 = 42 - let goo a = f(*Marker1*) 12 a - - type printer = System.Console - let z = (*Marker3*)printer.BufferWidth(*Marker2*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "Full name: Test.f") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "val f") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "property System.Console.BufferWidth: int") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker3*)","Full name: Test.printer") - [] - member public this.``Automation.Regression.ConstructorWithSameNameAsType.Bug2739``() = - let fileContent = """namespace AA - module AA = - type AA = | AA(*Marker1*) = 1 - | BB = 2 - type BB = { BB(*Marker2*) : string; }""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "AA.AA: AA") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "BB.BB: string") - [] - member public this.``Automation.Regression.EventImplementation.Bug5471``() = - let fileContent = """namespace regressiontest - open System - open System.Windows - open System.Windows.Input - - type CommandReference() = - inherit Freezable() - - static let commandProperty = - DependencyProperty.Register( - "Command", - typeof, - typeof, - PropertyMetadata(PropertyChangedCallback(fun o e -> CommandReference.OnCommandChanged(o, e)))) - - let evt = Event() - - member this.Command - with get () = this.GetValue(commandProperty) :?> ICommand - and set v = this.SetValue(commandProperty, (v: ICommand) ) - - interface ICommand with - - member this.CanExecute(parameter) = - if this.Command <> null then - this.Command.CanExecute(parameter) - else false - - member this.Execute(parameter) = - this.Command.Execute(parameter) - - [] - member x.CanExecuteChanged(*Marker*) = evt.Publish - - static member OnCommandChanged(d: DependencyObject, e: DependencyPropertyChangedEventArgs) = - let commandReference = (d :?> CommandReference) :> ICommand - let oldCommand = e.OldValue :?> ICommand - let newCommand = e.NewValue :?> ICommand - if oldCommand <> null then - // Error: This expression has type IEvent but is here used with type EventHandler - oldCommand.CanExecuteChanged.RemoveHandler(commandReference.CanExecuteChanged) - if newCommand <> null then - // Error: This expression has type IEvent but is here used with type EventHandler - newCommand.CanExecuteChanged.AddHandler(commandReference.CanExecuteChanged) - - override this.CreateInstanceCore() = - raise (NotImplementedException())""" - let (_, _, file) = this.CreateSingleFileProject(fileContent, references = ["PresentationCore"; "WindowsBase"]) - MoveCursorToStartOfMarker(file, "(*Marker*)") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - AssertContains(tooltip, "override CommandReference.CanExecuteChanged: IEvent") - AssertContains(tooltip, "regressiontest.CommandReference.CanExecuteChanged") - [] - member public this.``Automation.ExtensionMethod``() = - let fileContent ="""namespace TestQuickinfo - - module BCLExtensions = - type System.Random with - /// BCL class Extension method - member this.NextDice() = this.Next() + 1 - /// new BCL class Extension method with overload - member this.NextDice(a : bool) = this.Next() + 1 - /// existing BCL class Extension method with overload - member this.Next(a : bool) = this.Next() + 1 - /// BCL class Extension property - member this.DiceValue with get() = 6 - - type System.ConsoleKeyInfo with - /// BCL struct extension method - member this.ExtensionMethod() = 100 - /// BCL struct extension property - member this.ExtensionProperty with get() = "Foo" - - module OwnCode = - /// fs class - type FSClass() = - class - /// fs class method original - member this.Method(a:string) = "" - /// fs class property original - member this.Prop with get(a:string) = "" - end - - /// fs struct - type FSStruct(x:int) = - struct - end - - module OwnCodeExtensions = - type OwnCode.FSClass with - /// fs class extension method - member this.ExtensionMethod() = 100 - - /// fs class extension property - member this.ExtensionProperty with get() = "Foo" - - /// fs class method extension overload - member this.Method(a:int) = "" - - /// fs class property extension overload - member this.Prop with get(a:int) = "" - - type OwnCode.FSStruct with - /// fs struct extension method - member this.ExtensionMethod() = 100 - - /// fs struct extension property - member this.ExtensionProperty with get() = "Foo" - - module BCLClass = - open BCLExtensions - let rnd = new System.Random() - rnd.DiceValue(*Marker11*) |>ignore - rnd.NextDice(*Marker12*)() |>ignore - rnd.NextDice(*Marker13*)(true) |>ignore - rnd.Next(*Marker14*)(true) |>ignore - - - module BCLStruct = - open BCLExtensions - let cki = new System.ConsoleKeyInfo() - cki.ExtensionMethod(*Marker21*) |>ignore - cki.ExtensionProperty(*Marker22*) |>ignore - - module OwnClass = - open OwnCode - open OwnCodeExtensions - let rnd = new FSClass() - rnd.ExtensionMethod(*Marker31*) |>ignore - rnd.ExtensionProperty(*Marker32*) |>ignore - rnd.Method(*Marker33*)("") |>ignore - rnd.Method(*Marker34*)(6) |>ignore - rnd.Prop(*Marker35*)("") |>ignore - rnd.Prop(*Marker36*)(6) |>ignore - - module OwnStruct = - open OwnCode - open OwnCodeExtensions - let cki = new FSStruct(100) - cki.ExtensionMethod(*Marker41*) |>ignore - cki.ExtensionProperty(*Marker42*) |>ignore""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "property System.Random.DiceValue: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "BCL class Extension property") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "member System.Random.NextDice: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "BCL class Extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker13*)", "member System.Random.NextDice: a: bool -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker13*)", "new BCL class Extension method with overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker14*)", "member System.Random.Next: a: bool -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker14*)", "existing BCL class Extension method with overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "member System.ConsoleKeyInfo.ExtensionMethod: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "BCL struct extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "System.ConsoleKeyInfo.ExtensionProperty: string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "BCL struct extension property") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker31*)", "member FSClass.ExtensionMethod: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker31*)", "fs class extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker32*)", "FSClass.ExtensionProperty: string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker32*)", "fs class extension property") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker33*)", "member FSClass.Method: a: string -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker33*)", "fs class method original") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker34*)", "member FSClass.Method: a: int -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker34*)", "fs class method extension overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker35*)", "property FSClass.Prop: string -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker35*)", "fs class property original") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker36*)", "property FSClass.Prop: int -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker36*)", "fs class property extension overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker41*)", "member FSStruct.ExtensionMethod: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker41*)", "fs struct extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker42*)", "FSStruct.ExtensionProperty: string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker42*)", "fs struct extension property") +(*------------------------------------------IDE automation starts here -------------------------------------------------*) - [] - member public this.``Automation.Regression.GenericFunction.Bug2868``() = - let fileContent ="""module Test - // Hovering over a generic function (generic argument decorated with [] attribute yields a bad tooltip - let F (f :_ -> float<_>) = fun x -> f (x+1.0) - let rec Gen<[] 'u> (f:float<'u> -> float<'u>) = - Gen(*Marker*)(F f)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "val Gen: f: (float -> float) -> 'a") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "Exception" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "thrown" - - [] - member public this.``Automation.IdentifierHaveDiffMeanings``() = - let fileContent ="""namespace NS - module float(*Marker1_1*) = - - let GenerateTuple = fun x -> let tuple = (x,x.ToString(),(float(*Marker1_2*))x, ( fun y -> (y.ToString(),y+1)) ) - tuple - - let MySeq : (*Marker2_1*)seq = - seq(*Marker2_2*) { - - for i in 1..9 do - - let myTuple = GenerateTuple i - let fieldInt,fieldString,fieldFloat,_ = myTuple - yield fieldFloat - } - - let MySet : (*Marker3_1*)Set = - MySeq - |> Array.ofSeq - |> List.ofArray - |> Set(*Marker3_2*).ofList - let int(*Marker4_1*) : int(*Marker4_2*) = 1 - type int(*Marker4_3*)() = - member this.M = 1 - type T(*Marker5_1*)() = - [] - val mutable T : T - let T = new T() - let t = T.T.T.T(*Marker5_2*); - - type ValType() = - member this.Value with get(*Marker6_1*) () = 10 - and set(*Marker6_2*) x = x + 1 |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_1*)", "module float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_2*)", "val float: 'T -> float (requires member op_Explicit)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_2*)", "Full name: Microsoft.FSharp.Core.Operators.float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_3*)", "type float = System.Double") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_3*)", "Full name: Microsoft.FSharp.Core.float") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker2_1*)","type seq<'T> = System.Collections.Generic.IEnumerable<'T>") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker2_1*)","Full name: Microsoft.FSharp.Collections.seq<_>") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_2*)", "val seq: 'T seq -> 'T seq") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_2*)", "Full name: Microsoft.FSharp.Core.Operators.seq") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker3_1*)","type Set<'T (requires comparison)> =") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker3_1*)","Full name: Microsoft.FSharp.Collections.Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_2*)", "module Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_2*)", "Functional programming operators related to the Set<_> type") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_1*)", "val int: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_1*)", "Full name: NS.float.int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_2*)", "type int = int32") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_2*)", "Full name: Microsoft.FSharp.Core.int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_3*)", "type int =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_3*)", "member M: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "type T =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "new : unit -> T") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "val mutable T: T") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_2*)", "T.T: T") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6_1*)", "member ValType.Value : int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6_2*)", "member ValType.Value : int with set") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker6_2*)" "Microsoft.FSharp.Core.ExtraTopLevelOperators.set" - [] - member public this.``Automation.Regression.ModuleIdentifier.Bug2937``() = - let fileContent ="""module XXX(*Marker*) - type t = C3""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "module XXX") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "\n" - [] - member public this.``Automation.Regression.NamesArgument.Bug3818``() = - let fileContent ="""module m - [] - type T = class - end""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "property System.AttributeUsageAttribute.AllowMultiple: bool") - - [] - member public this.``Automation.OnUnitsOfMeasure``() = - let fileContent ="""namespace TestQuickinfo - - module TestCase1 = - [] - /// this type represents kilogram in UOM - type kg - let mass(*Marker11*) = 2.0 - - module TestCase2 = - [] - /// use Set as the type name of UoM - type Set - - let v1 = [1.0 .. 2.0 .. 5.0] |> Seq.item 1 - - (if v1 = 3.0 then 0 else 1) |> ignore - - let twoSets = 2.0 - - [1.0] - |> Set.ofList - |> Set(*Marker22*).isEmpty - |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "val mass: float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "Full name: TestQuickinfo.TestCase1.mass") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "inherits: System.ValueType") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "[]") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "type kg") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "this type represents kilogram in UOM") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "Full name: TestQuickinfo.TestCase1.kg") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "[]") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "type Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "use Set as the type name of UoM") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "Full name: TestQuickinfo.TestCase2.Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "module Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "from Microsoft.FSharp.Collections") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "Functional programming operators related to the Set<_> type.") - [] - member public this.``Automation.OverRiddenMembers``() = - let fileContent ="""namespace QuickinfoGeneric - - module FSharpOwnCode = - [] - type TextOutputSink() = - abstract WriteChar : char -> unit - abstract WriteString : string -> unit - default x.WriteString(s) = s |> String.iter x.WriteChar - - type ByteOutputSink() = - inherit TextOutputSink() - default sink.WriteChar(c) = System.Console.Write(c) - override sink.WriteString(s) = System.Console.Write(s) - - let sink = new ByteOutputSink() - sink.WriteChar(*Marker11*)('c') - sink.WriteString(*Marker12*)("Hello World!")""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "override ByteOutputSink.WriteChar: c: char -> unit") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "override ByteOutputSink.WriteString: s: string -> unit") - [] - member public this.``Automation.Regression.QuotedIdentifier.Bug3790``() = - let fileContent ="""module Test - module ``Some``(*Marker1*) = Microsoft.FSharp.Collections.List - let _ = ``Some``(*Marker2*).append [] [] """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "``(*Marker1*)", "module List") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "``(*Marker1*)" "Option.Some" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "``(*Marker2*)", "module List") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "``(*Marker2*)" "Option.Some" - - [] - member public this.``Automation.Setter``() = - let fileContent ="""type T() = - member this.XX - with set ((a:int), (b:int), (c:int)) = () - - (new T()).XX(*Marker1*) <- (1,2,3) - //=================================================== - // More cases: - //=================================================== - type IFoo = interface - abstract foo : int -> int - end - let i : IFoo = Unchecked.defaultof - i.foo(*Marker2*) |> ignore - //=================================================== - type Rec = { bar:int->int->int } - let r = {bar = fun x y -> x + y } - - r.bar(*Marker3*) 1 2 |>ignore - //=================================================== - type M() = - member this.baz x y = x + y - let m = new M() - m.baz(*Marker3*) 1 2 |>ignore - //=================================================== - type T2() = - member this.Foo(a,b) = "" - let t = new T2() - t.Foo(*Marker4*)(1,2) |>ignore - //=================================================== - let foo (x:int) (y:int) : int = 1 - foo(*Marker5*) 2 3 |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "T.XX: int * int * int") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker1*)" "->" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "IFoo.foo: int -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "Rec.bar: int -> int -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4*)", "T2.Foo: a: 'a * b: 'b -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5*)", "val foo: int -> int -> int") - [] - member public this.``Automation.Regression.TupleException.Bug3723``() = - let fileContent ="""namespace TestQuickinfo - exception E3(*Marker1*) of int * int - exception E4(*Marker2*) of (int * int) - exception E5(*Marker3*) = E4""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "exception E3 of int * int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "Full name: TestQuickinfo.E3") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "exception E4 of (int * int)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "Full name: TestQuickinfo.E4") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "exception E5 = E4") - [] - member public this.``Automation.TypeAbbreviations``() = - let fileContent ="""namespace NS - module TypeAbbreviation = - - type MyInt(*Marker1_1*) = int - - type PairOfFloat(*Marker2_1*) = float * float - - - type AbAttrName(*Marker5_1*) = AbstractClassAttribute - - - type IA(*Marker3_1*) = - abstract AbstractMember : int -> int - - [] - type ClassIA(*Marker3_2*)() = - interface IA with - member this.AbstractMember x = x + 1 - - type GenericClass(*Marker4_1*)<'a when 'a :> IA>() = - static member StaticMember(x:'a) = x.AbstractMember(1) - let GenerateTuple = fun ( x : MyInt) -> - let myInt(*Marker1_2*),float1,float2,function1 = (x,(float)x,(float)x, ( fun y -> (y.ToString(),y+1)) ) - myInt,((float1,float2):PairOfFloat),function1 - let MySeq(*Marker2_2*) = - seq { - - for i in 1..9 do - let myInt,pairofFloat,function1 = GenerateTuple i - - yield pairofFloat - } - - let genericClass(*Marker4_2*) = new GenericClass()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_1*)", "type MyInt = int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_2*)", "val myInt: MyInt") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_1*)", "type PairOfFloat = float * float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_2*)", "val MySeq: PairOfFloat seq") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_1*)", "type IA =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_2*)", "type ClassIA =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_1*)", "type GenericClass<'a (requires 'a :> IA)> =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_2*)", "val genericClass: GenericClass") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "type AbAttrName = AbstractClassAttribute") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_2*)", "type AbAttrName = AbstractClassAttribute") - [] - member public this.``Automation.Regression.TypeInferenceScenarios.Bug2362&3538``() = - let fileContent ="""module Test.Module1 - open System - open System.Diagnostics - open System.Runtime.InteropServices - #nowarn "9" - let append m(*Marker1*) n(*Marker2*) = fun ac(*Marker3*) -> m (n ac) - type Foo() as this(*Marker4*) = - do this(*Marker5*) |> ignore - member this.Bar() = - this(*Marker6*) |> ignore - () - [] - type A = - [] - val mutable x : int - new () = { } - member this.Prop = this.x - - let x = new (*Marker7*)A()""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "val m: ('a -> 'b)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "val n: ('c -> 'a)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "val ac: 'c") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4*)", "val this: Foo") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5*)", "val this: Foo") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6*)", "val this: Foo") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker7*)","type A =") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker7*)","val mutable x: int") - [] - member public this.``Automation.Regression.TypemoduleConstructorLastLine.Bug2494``() = - let fileContent ="""namespace NS - open System - //regression test for bug 2494 - - type PriorityQueue(*MarkerType*)<'k,'a> = - | Nil(*MarkerDataConstructor*) - | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a> - - module PriorityQueue(*Marker3*) = - let empty = Nil - - let minKeyValue = function - | Nil -> failwith "empty queue" - | Branch(k,a,_,_) -> (k,a) - - let minKey pq = fst (minKeyValue pq(*MarkerVal*)) - - let singleton(*MarkerLastLine*) k a = Branch(k,a,Nil,Nil)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerType*)", "type PriorityQueue") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerDataConstructor*)", "union case PriorityQueue.Nil: PriorityQueue<'k,'a>") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "module PriorityQueue") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerVal*)", "val pq: PriorityQueue<'a,'b>") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerLastLine*)", "val singleton: k: 'a -> a: 'b -> PriorityQueue<'a,'b>") - [] - member public this.``Automation.WhereQuickInfoShouldNotShowUp``() = - let fileContent ="""namespace Test - - module Helper = - /// Tests if passed System.Numerics.BigInteger(*Marker1*) argument is prime - let IsPrime x = - let mutable i = 2I - let mutable foundFactor = false - while not foundFactor && i < x do - (* - the most naive way to test for number being prime - Works great for small int(*Marker2*) - *) - if x % i = 0I then - foundFactor <- true - i <- i + 1I - not foundFactor - - module App = - open Helper - - let sumOfAllPrimesUnder1Mi = - #if TEST_TWO_MI - seq(*Marker4*) { 1I .. 2000000I } - #else - seq { 1I .. 1000000I(*Marker7*) } - #endif - |> Seq.filter(IsPrime) - // find result after filtering seq(*Marker3*) - |> Seq.sum - - let myString hello = "hello"(*Marker5*) - - myString "myString"(*Marker8*) - |> Seq.filter (fun c -> int c > 75) - |> Seq.item 0 - |> (=) 'e'(*Marker6*) - |> ignore""" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker1*)" "BigInteger" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker2*)" "int" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker3*)" "seq" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker4*)" "seq" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker5*)" "hello" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker6*)" "char" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker7*)" "bigint" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker8*)" "myString" - - [] - member public this.``Automation.Regression.XmlDocComments.Bug3157``() = - let fileContent ="""namespace TestQuickinfo - module XmlComment = - /// XmlComment J - let func(*Marker*) x = - /// XmlComment K - let rec g x = 1 - g x""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "val func: x: 'a -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "XmlComment J") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "Full name: TestQuickinfo.XmlComment.func") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "XmlComment K" - - [] - member public this.``Automation.Regression.XmlDocCommentsOnExtensionMembers.Bug138112``() = - let fileContent ="""module Module1 = - type T() = - /// XmlComment M1 - member this.M1() = () - type T with - /// XmlComment M2 - member this.M2() = () - module public Extension = - type T with - /// XmlComment M3 - member this.M3() = () - open Module1 - open Extension - - let x1 = T().M1(*Marker1*)() - let x2 = T().M2(*Marker2*)() - let x3 = T().M3(*Marker3*)()""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "XmlComment M1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "XmlComment M2") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "XmlComment M3") - - [] - member public this.XmlDocCommentsForArguments() = - let fileContent = """ - type bar() = - /// Test for members - /// x1 param! - member this.foo - (x1:int)= - System.Console.WriteLine(x1.ToString()) - - type Uni1 = - /// Test for unions - /// str of case1 - | Case1 of str: string - | None - - /// Test for exception types - /// value param - exception Ex1 of value: string - - // Methods - let f1 = (new bar()).foo(*Marker0*)(x1(*Marker1*) = 10) - let f2 = System.String.Concat(1, arg1(*Marker2*) = "") - - //Unions - let f3 = Case1(str(*Marker3*) = "10") - match f3 with - | Case1(str(*Marker4*) = "10") -> () - | _ -> () - - //Exceptions - let f4 = Ex1(value(*Marker5*) = "") - try - () - with - Ex1(value(*Marker6*) = v) -> () - - //Static parameters of type providers - type provType = N1.T - """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker0*)", "Test for members") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "x1 param!") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "Concatenates the string representations of two specified objects.") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "str of case1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4*)", "str of case1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5*)", "value param") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6*)", "value param") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker7*)", "Param1 of string", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker8*)", "Ignored", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) member private this.VerifyUsingFsTestLib fileContent queries crossProject = use _guard = this.UsingNewVS() @@ -2952,139 +517,6 @@ query." AssertContains(tooltip, expectedTip) - [] - member public this.``Automation.XDelegateDUStructfromOwnCode``() = - let fileContent ="""module Test - - open FSTestLib - - open System.Runtime.InteropServices - let ctrlSignal = ref false - [] - extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) - let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) - let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) - - let IsInstanceMethod (controlEventHandler:ControlEventHandler) = - // TC 32 Identifier Delegate Own Code Pattern Match - match controlEventHandler(*Marker1*).Method.IsStatic with - | true -> printf "It's not a instance method. " - | false -> printf " It's a instance method. " - - // TC 33 Event DiscUnion Own Code Quotation - let a = <@ MyDistance.Event(*Marker2*) @> - - let DelegateSeq = - seq { for i in 1..10 do - let newDelegate = new ControlEventHandler(MyCar.Run) - // TC 35 Identifier Delegate Own Code Comp Expression - yield newDelegate(*Marker3*) } - - let StructFieldSeq = - seq { for i in 1..10 do - let a = MyPoint((float)i,2.0) - // TC 36 Field Struct Own Code Comp Expression - yield a.X(*Marker4*) }""" - let queries = [("(*Marker1*)", "val controlEventHandler: ControlEventHandler"); - ("(*Marker2*)", "property MyDistance.Event: Event"); - ("(*Marker3*)", "val newDelegate: ControlEventHandler"); - ("(*Marker4*)", "property MyPoint.X: float"); - ("(*Marker4*)", "Gets and sets X")] - this.VerifyUsingFsTestLib fileContent queries false - - [] - member public this.``Automation.StructDelegateDUfromOwnCode``() = - let fileContent ="""module Test - - open FSTestLib - - open System.Runtime.InteropServices - let ctrlSignal = ref false - [] - extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) - let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) - let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) - - let IsInstanceMethod (controlEventHandler:ControlEventHandler) = - // TC 32 Identifier Delegate Own Code Pattern Match - match controlEventHandler(*Marker1*).Method.IsStatic with - | true -> printf "It's not a instance method. " - | false -> printf " It's a instance method. " - - // TC 33 Event DiscUnion Own Code Quotation - let a = <@ MyDistance.Event(*Marker2*) @> - - - let DelegateSeq = - seq { for i in 1..10 do - let newDelegate = new ControlEventHandler(MyCar.Run) - // TC 35 Identifier Delegate Own Code Comp Expression - yield newDelegate(*Marker3*) } - - let StructFieldSeq = - seq { for i in 1..10 do - let a = MyPoint((float)i,2.0) - // TC 36 Field Struct Own Code Comp Expression - yield a.X(*Marker4*) }""" - let queries = [("(*Marker1*)", "val controlEventHandler: ControlEventHandler"); - ("(*Marker2*)", "property MyDistance.Event: Event"); - ("(*Marker3*)", "val newDelegate: ControlEventHandler"); - ("(*Marker4*)", "property MyPoint.X: float"); - ("(*Marker4*)", "Gets and sets X"); - ] - this.VerifyUsingFsTestLib fileContent queries false - - [] - member public this.``Automation.TupleRecordClassfromOwnCode``() = - let fileContent ="""module Test - - open FSTestLib - - let AbsTuple = fun x -> let tuple1 = (x,x.ToString(),(float)x, ( fun y -> (y.ToString(),y+1)) ) - let tuple2 = (-x,(-x).ToString(),(float)(-x), ( fun y -> (y.ToString(),y+1)) ) - if x >= 0 then - // TC 29 Self Tuple Own Code Imperative - tuple1(*Marker1*) - else - tuple2 - - let GenerateMyEmployee name age = - let a = MyEmployee.MakeDummy() - a.Name <- name - a.Age <- age - a.IsFTE <- System.Convert.ToBoolean(System.Random().Next(2)) - match a.IsFTE with - | true -> a - // TC 30 Operator Record Own Code Pattern Match - | _ -> MyEmployee(*Marker2*).MakeDummy() - - // TC 31 Self Class Own Code Quotation - let myCarQuot = <@ new MyCar(*Marker3*)(19,MyColors.Red) @> - - open System.Runtime.InteropServices - let ctrlSignal = ref false - [] - extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) - let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) - let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) - - let MaxTuple x y = - let tuplex = (x,x.ToString() ) - let tupley = (y,(y).ToString()) - match x>y with - // TC 34 Operator Tuple Own Code Pattern Match - | true -> tuplex(*Marker4*) - | false -> tupley""" - let queries = [("(*Marker1*)", "val tuple1: int * string * float * (int -> string * int)"); - ("(*Marker2*)", "type MyEmployee"); - ("(*Marker2*)", "Full name: FSTestLib.MyEmployee"); - ("(*Marker3*)", "type MyCar"); - ("(*Marker3*)", "Full name: FSTestLib.MyCar"); - ("(*Marker4*)", "val tuplex: 'a * string") - ] - this.VerifyUsingFsTestLib fileContent queries false - -(*------------------------------------------IDE Query automation start -------------------------------------------------*) member private this.AssertQuickInfoInQuery(code: string, mark : string, expectedstring : string) = use _guard = this.UsingNewVS() @@ -3130,179 +562,6 @@ query." gpatcc.AssertExactly(0,0) - [] - // QuickInfo still works on valid operators in a query with errors elsewhere in it - member public this.``Query.WithError1.Bug196137``() = - let fileContent =""" - open DataSource - // get the product list, defined in another file, see AssertQuickInfoInQuery - let products = Products.getProductList() - let sortedProducts = - query { - for p in products do - let x = p.ProductID + "a" - sortBy p.ProductName(*Mark*) - select p - }""" - this.AssertQuickInfoInQuery (fileContent, "(*Mark*)", "Product.ProductName: string") - - [] - // QuickInfo still works on valid operators in a query with errors elsewhere in it - member public this.``Query.WithError2``() = - let fileContent =""" - open DataSource - let products = Products.getProductList() - let test = - query { - for p in products do - let x = p.ProductID + "1" - minBy(*Mark*) p.UnitPrice - }""" - this.AssertQuickInfoInQuery (fileContent, "(*Mark*)", "custom operation: minBy ('Value)") - - [] - // QuickInfo works in a large query (using many operators) - member public this.``Query.WithinLargeQuery``() = - let fileContent =""" - open DataSource - let products = Products.getProductList() - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let largequery = - query { - for p in products do - sortBy p.ProductName - thenBy p.UnitPrice - thenByDescending p.Category - where (p.UnitsInStock < 100) - where (p.Category = "Condiments") - groupValBy(*Mark1*) p p.Category into g - let maxPrice = query { for x in g do maxBy(*Mark2*) x.UnitPrice } - let mostExpensiveProducts = query { for x in g do where (x.UnitPrice = maxPrice) } - select (g.Key, mostExpensiveProducts, query { - for n in numbers do - where (n%2 = 0) - where(*Mark3*) (n > 2) - where (n < 40) - select n}) - distinct(*Mark4*) - }""" - this.AssertQuickInfoInQuery (fileContent, "(*Mark1*)", "custom operation: groupValBy ('Value) ('Key)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark2*)", "custom operation: maxBy ('Value)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark3*)", "custom operation: where (bool)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark4*)", "custom operation: distinct") - - [] - // Arguments to query operators have correct QuickInfo - // quickinfo should be correct including when the operator is causing an error - member public this.``Query.ArgumentToQuery.OperatorError``() = - let fileContent =""" - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let foo = - query { - for n in numbers do - orderBy (n.GetType()) - select n}""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "n.GetType()", "val n: int",queryAssemblyRefs) - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "Type()", "System.Object.GetType() : System.Type",queryAssemblyRefs) - - [] - // Arguments to query operators have correct QuickInfo - // quickinfo should be correct In a nested query - member public this.``Query.ArgumentToQuery.InNestedQuery``() = - let fileContent =""" - open DataSource - let products = Products.getProductList() - let test1 = - query { - for p in products do - sortBy p.ProductName - select (p.ProductName, query { for f in products do - groupValBy(*Mark3*) f f.Category into g - let maxPrice = query { for x in g do maxBy x.UnitPrice } - let mostExpensiveProducts = query { for x in g do where(*Mark1*) (x.UnitPrice = maxPrice(*Mark2*)) } - select(*Mark4*) (g.Key, g)}) } """ - this.AssertQuickInfoInQuery (fileContent, "(*Mark1*)", "custom operation: where (bool)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark2*)", "val maxPrice: decimal") - this.AssertQuickInfoInQuery (fileContent, "(*Mark3*)", "custom operation: groupValBy ('Value) ('Key)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark4*)", "custom operation: select ('Result)") - - [] - // A computation expression with its own custom operators has correct QuickInfo displayed - member public this.``Query.ComputationExpression.Method``() = - let fileContent =""" - open System.Collections.Generic - let chars = ["A";"B";"C"] - type WorkflowBuilder() = - - let yieldedItems = new List() - member this.Items = yieldedItems |> Array.ofSeq - - member this.Yield(item) = yieldedItems.Add(item) - member this.YieldFrom(items : seq) = - items |> Seq.iter (fun item -> yieldedItems.Add(item.ToUpper())) - () - - member this.Combine(f, g) = g - member this.Delay (f : unit -> 'a) = - f() - - member this.Zero() = () - member this.Return _ = this.Items - - let computationExpreQuery = - query { - for char in chars do - let workflow = new WorkflowBuilder() - let result = - workflow { - yield "foo" - yield "bar" - yield! [| "a"; "b"; "c" |] - - return () - } - let t = workflow.Combine(*Mark1*)("a","b") - let d = workflow.Zero(*Mark2*)() - where (result |> Array.exists(fun i -> i = char)) - yield char - } """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark1*)", "member WorkflowBuilder.Combine: f: 'b0 * g: 'c1 -> 'c1",queryAssemblyRefs) - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark2*)", "member WorkflowBuilder.Zero: unit -> unit",queryAssemblyRefs) - - [] - // A computation expression with its own custom operators has correct QuickInfo displayed - member public this.``Query.ComputationExpression.CustomOp``() = - let fileContent =""" - open System - open Microsoft.FSharp.Quotations - - type EventBuilder() = - member _.For(ev:IObservable<'T>, loop:('T -> #IObservable<'U>)) : IObservable<'U> = failwith "" - member _.Yield(v:'T) : IObservable<'T> = failwith "" - member _.Quote(v:Quotations.Expr<'T>) : Expr<'T> = v - member _.Run(x:Expr<'T>) = Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation x :?> 'T - - [] - member _.Where (x, [] f) = Observable.filter f x - - [] - member _.Select (x, [] f) = Observable.map f x - - [] - member inline _.ScanSumBy (source, [] f : 'T -> 'U) : IObservable<'U> = Observable.scan (fun a b -> a + f b) LanguagePrimitives.GenericZero<'U> source - - let myquery = EventBuilder() - let f = new Event() - let e1 = - myquery { for x in f.Publish do - myWhere(*Mark1*) (fst x < 100) - scanSumBy(*Mark2*) (snd x) - } """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark1*)", "custom operation: myWhere (bool)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark1*)", "Calls EventBuilder.Where") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark2*)", "custom operation: scanSumBy ('U)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark2*)", "Calls EventBuilder.ScanSumBy") - // Context project system type UsingProjectSystem() = diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs index 40efc4655a8..5f3c941d2b6 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs @@ -1,166 +1,11 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -namespace Tests.LanguageService - -open System -open Xunit -open FSharp.Compiler.EditorServices - -type QuickParse() = +// The QuickParse unit tests that used to live here (the CheckGetPartialLongName member and the +// CheckIsland0..CheckIsland50 members) were direct public-API tests of +// FSharp.Compiler.EditorServices.QuickParse with no Salsa harness. They were migrated to the +// cross-platform corpus at tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs (M2 +// quickparse batch 1), where the CheckIsland family is a single parametrized Theory, the +// GetPartialLongNameEx checks are a second parametrized Theory, and the commented-out +// CheckIsland25 is a skipped Fact. This file is intentionally left as an empty namespace. - let CheckIsland(tolerateJustAfter:bool, s : string, p : int, expected) = - let actual = - match QuickParse.GetCompleteIdentifierIsland tolerateJustAfter s p with - | Some (s, col, _) -> Some (s, col) - | None -> None - Assert.Equal(expected, actual) - - [] - member public qp.CheckGetPartialLongName() = - let CheckAt(line, index, expected) = - let actual = QuickParse.GetPartialLongNameEx(line, index) - if (actual.QualifyingIdents, actual.PartialIdent, actual.LastDotPos) <> expected then - failwithf "Expected %A but got %A" expected actual - - let Check(line,expected) = - CheckAt(line, line.Length-1, expected) - - Check("let y = List.",(["List"], "", Some 12)) - Check("let y = List.conc",(["List"], "conc", Some 12)) - Check("let y = S", ([], "S", None)) - Check("S", ([], "S", None)) - Check("let y=", ([], "", None)) - Check("Console.Wr", (["Console"], "Wr", Some 7)) - Check(" .", ([""], "", Some 1)) - Check(".", ([""], "", Some 0)) - Check("System.Console.Wr", (["System";"Console"],"Wr", Some 14)) - Check("let y=f'", ([], "f'", None)) - Check("let y=SomeModule.f'", (["SomeModule"], "f'", Some 16)) - Check("let y=Some.OtherModule.f'", (["Some";"OtherModule"], "f'", Some 22)) - Check("let y=f'g", ([], "f'g", None)) - Check("let y=SomeModule.f'g", (["SomeModule"], "f'g", Some 16)) - Check("let y=Some.OtherModule.f'g", (["Some";"OtherModule"], "f'g", Some 22)) - Check("let y=FSharp.Data.File.``msft-prices.csv``", ([], "", None)) - Check("let y=FSharp.Data.File.``msft-prices.csv", (["FSharp";"Data";"File"], "msft-prices.csv", Some 22)) - Check("let y=SomeModule. f", (["SomeModule"], "f", Some 16)) - Check("let y=SomeModule .f", (["SomeModule"], "f", Some 18)) - Check("let y=SomeModule . f", (["SomeModule"], "f", Some 18)) - Check("let y=SomeModule .", (["SomeModule"], "", Some 18)) - Check("let y=SomeModule . ", (["SomeModule"], "", Some 18)) - - - [] - member public qp.CheckIsland0() = CheckIsland(true, "", -1, None) - [] - member public qp.CheckIsland1() = CheckIsland(false, "", -1, None) - - [] - member public qp.CheckIsland2() = CheckIsland(true, "", 0, None) - [] - member public qp.CheckIsland3() = CheckIsland(false, "", 0, None) - - [] - member public qp.CheckIsland4() = CheckIsland(true, null, 0, None) - [] - member public qp.CheckIsland5() = CheckIsland(false, null, 0, None) - - [] - member public qp.CheckIsland6() = CheckIsland(false, "identifier", 0, Some("identifier",10)) - [] - member public qp.CheckIsland7() = CheckIsland(false, "identifier", 8, Some("identifier",10)) - - [] - member public qp.CheckIsland8() = CheckIsland(true, "identifier", 0, Some("identifier",10)) - [] - member public qp.CheckIsland9() = CheckIsland(true, "identifier", 8, Some("identifier",10)) - - // A place where tolerateJustAfter matters - [] - member public qp.CheckIsland10() = CheckIsland(false, "identifier", 10, None) - [] - member public qp.CheckIsland11() = CheckIsland(true, "identifier", 10, Some("identifier",10)) - - // Index which overflows the line - [] - member public qp.CheckIsland12() = CheckIsland(true, "identifier", 11, None) - [] - member public qp.CheckIsland13() = CheckIsland(false, "identifier", 11, None) - - // Match active pattern identifiers - [] - member public qp.CheckIsland14() = CheckIsland(false, "|Identifier|", 0, Some("|Identifier|",12)) - [] - member public qp.CheckIsland15() = CheckIsland(true, "|Identifier|", 0, Some("|Identifier|",12)) - [] - member public qp.CheckIsland16() = CheckIsland(false, "|Identifier|", 12, None) - [] - member public qp.CheckIsland17() = CheckIsland(true, "|Identifier|", 12, Some("|Identifier|",12)) - [] - member public qp.CheckIsland18() = CheckIsland(false, "|Identifier|", 13, None) - [] - member public qp.CheckIsland19() = CheckIsland(true, "|Identifier|", 13, None) - - // ``Quoted`` identifiers - [] - member public qp.CheckIsland20() = CheckIsland(false, "``Space Man``", 0, Some("``Space Man``",13)) - [] - member public qp.CheckIsland21() = CheckIsland(true, "``Space Man``", 0, Some("``Space Man``",13)) - [] - member public qp.CheckIsland22() = CheckIsland(false, "``Space Man``", 10, Some("``Space Man``",13)) - [] - member public qp.CheckIsland23() = CheckIsland(true, "``Space Man``", 10, Some("``Space Man``",13)) - [] - member public qp.CheckIsland24() = CheckIsland(false, "``Space Man``", 11, Some("``Space Man``",13)) - // [] - // member public qp.CheckIsland25() = CheckIsland(true, "``Space Man``", 11, Some("Man",11)) // This is probably not what the user wanted. Not enforcing this test. - [] - member public qp.CheckIsland26() = CheckIsland(false, "``Space Man``", 12, Some("``Space Man``",13)) - [] - member public qp.CheckIsland27() = CheckIsland(true, "``Space Man``", 12, Some("``Space Man``",13)) - [] - member public qp.CheckIsland28() = CheckIsland(false, "``Space Man``", 13, None) - [] - member public qp.CheckIsland29() = CheckIsland(true, "``Space Man``", 13, Some("``Space Man``",13)) - [] - member public qp.CheckIsland30() = CheckIsland(false, "``Space Man``", 14, None) - [] - member public qp.CheckIsland31() = CheckIsland(true, "``Space Man``", 14, None) - [] - member public qp.CheckIsland32() = CheckIsland(true, "``msft-prices.csv``", 14, Some("``msft-prices.csv``",19)) - // handle extracting islands from arrays - [] - member public qp.CheckIsland33() = CheckIsland(true, "[|abc;def|]", 2, Some("abc",5)) - [] - member public qp.CheckIsland34() = CheckIsland(true, "[|abc;def|]", 4, Some("abc",5)) - [] - member public qp.CheckIsland35() = CheckIsland(true, "[|abc;def|]", 5, Some("abc",5)) - [] - member public qp.CheckIsland36() = CheckIsland(true, "[|abc;def|]", 6, Some("def",9)) - [] - member public qp.CheckIsland37() = CheckIsland(true, "[|abc;def|]", 8, Some("def",9)) - [] - member public qp.CheckIsland38() = CheckIsland(true, "[|abc;def|]", 9, Some("def",9)) - [] - member public qp.CheckIsland39() = CheckIsland(false, "identifier(*boo*)", 0, Some("identifier",10)) - [] - member public qp.CheckIsland40() = CheckIsland(true, "identifier(*boo*)", 0, Some("identifier",10)) - [] - member public qp.CheckIsland41() = CheckIsland(false, "identifier(*boo*)", 10, None) - [] - member public qp.CheckIsland42() = CheckIsland(true, "identifier(*boo*)", 10, Some("identifier",10)) - [] - member public qp.CheckIsland43() = CheckIsland(false, "identifier(*boo*)", 11, None) - [] - member public qp.CheckIsland44() = CheckIsland(true, "identifier(*boo*)", 11, None) - [] - member public qp.CheckIsland45() = CheckIsland(false, "``Space Man (*boo*)``", 13, Some("``Space Man (*boo*)``",21)) - [] - member public qp.CheckIsland46() = CheckIsland(true, "``Space Man (*boo*)``", 13, Some("``Space Man (*boo*)``",21)) - [] - member public qp.CheckIsland47() = CheckIsland(false, "(*boo*)identifier", 11, Some("identifier",17)) - [] - member public qp.CheckIsland48() = CheckIsland(true, "(*boo*)identifier", 11, Some("identifier",17)) - [] - member public qp.CheckIsland49() = CheckIsland(false, "identifier(*(* *)boo*)", 0, Some("identifier",10)) - [] - member public qp.CheckIsland50() = CheckIsland(true, "identifier(*(* *)boo*)", 0, Some("identifier",10)) +namespace Tests.LanguageService diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs index dbb2b996de2..43b5ec39b99 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs @@ -130,775 +130,6 @@ type UsingMSBuild() as this = let tooltip = GetQuickInfoAtCursor file AssertNotContains(tooltip, notexpected) - /// There was a problem with Salsa that caused squiggles not to be shown for .fsx files. - [] - member public this.``Fsx.Squiggles.ShowInFsxFiles``() = - let fileContent = """open Thing1.Thing2""" - this.VerifyFSXErrorListContainedExpectedString(fileContent,"Thing1") - - /// Regression test for FSharp1.0:4861 - #r to nonexistent file causes the first line to be squiggled - /// There was a problem with Salsa that caused squiggles not to be shown for .fsx files. - [] - member public this.``Fsx.Hash.RProperSquiggleForNonExistentFile``() = - let fileContent = """#r "NonExistent" """ - this.VerifyFSXErrorListContainedExpectedString(fileContent,"was not found or is invalid") - - /// Nonexistent hash. There was a problem with Salsa that caused squiggles not to be shown for .fsx files. - [] - member public this.``Fsx.Hash.RDoesNotExist.Bug3325``() = - let fileContent = """#r "ThisDLLDoesNotExist" """ - this.VerifyFSXErrorListContainedExpectedString(fileContent,"'ThisDLLDoesNotExist' was not found or is invalid") - - // There was a spurious error message on the first line. - [] - member public this.``Fsx.ExactlyOneError.Bug4861``() = - let code = - ["//" // First line is important in this repro - "#r \"Nonexistent\"" - ] - let (project, _) = createSingleFileFsxFromLines code - AssertExactlyCountErrorSeenContaining(project, "Nonexistent", 1) // ...and not an error on the first line. - - [] - member public this.``Fsx.InvalidHashLoad.ShouldBeASquiggle.Bug3012``() = - let fileContent = """ - #load "Bar.fs" - """ - this.VerifyFSXErrorListContainedExpectedString(fileContent,"Bar.fs") - - // Transitive to existing property. - [] - member public this.``Fsx.ScriptClosure.TransitiveLoad1``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let file1 = OpenFile(project,"File1.fs") - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fs\"" - ]) - let script2 = OpenFile(project,"Script2.fsx") - let script2 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script1.fsx\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - // Transitive to nonexisting property. - [] - member public this.``Fsx.ScriptClosure.TransitiveLoad2``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fs\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "Namespace.Foo.NonExistingProperty" - ]) - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - AssertExactlyOneErrorSeenContaining(project, "NonExistingProperty") - - /// FEATURE: Typing a #r into a file will cause it to be recognized by intellisense. - [] - member public this.``Fsx.HashR.AddedIn``() = - let code = - [ - "//#r \"System.Transactions.dll\"" // Pick anything that isn't in the standard set of assemblies. - "open System.Transactions" - ] - let (project, file) = createSingleFileFsxFromLines code - VerifyErrorListContainedExpectedStr("Transactions",project) - - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - ReplaceFileInMemory file - [ - "#r \"System.Transactions.dll\"" // <-- Uncomment this line - "open System.Transactions" - ] - AssertNoErrorsOrWarnings(project) - gpatcc.AssertExactly(notAA[file],notAA[file], true (* expectCreate, because dependent DLL set changed *)) - - // FEATURE: Adding a #load to a file will cause types from that file to be visible in intellisense - [] - member public this.``Fsx.HashLoad.Added``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - [ - "namespace MyNamespace" - " module MyModule =" - " let x = 1" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "//#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ]) - let fsx = OpenFile(project,"File2.fsx") - VerifyErrorListContainedExpectedStr("MyNamespace",project) - - ReplaceFileInMemory fsx - [ - "#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ] - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - // FEATURE: Removing a #load to a file will cause types from that file to no longer be visible in intellisense - [] - member public this.``Fsx.HashLoad.Removed``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - [ - "namespace MyNamespace" - " module MyModule =" - " let x = 1" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ]) - let fsx = OpenFile(project,"File2.fsx") - AssertNoErrorsOrWarnings(project) - - ReplaceFileInMemory fsx - [ - "//#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ] - TakeCoffeeBreak(this.VS) - VerifyErrorListContainedExpectedStr("MyNamespace",project) - - [] - member public this.``Fsx.HashLoad.Conditionals``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - ["module InDifferentFS" - "#if INTERACTIVE" - "let x = 1" - "#else" - "let y = 2" - "#endif" - "#if DEBUG" - "let A = 3" - "#else" - "let B = 4" - "#endif" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - "InDifferentFS." - ]) - let fsx = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(fsx, "InDifferentFS.") - let completion = AutoCompleteAtCursor fsx - let completion = completion |> Array.map (fun (CompletionItem(name, _, _, _, _)) -> name) |> set - Assert.Equal(Set.count completion, 2) - Assert.True(completion.Contains "x", "Completion list should contain x because INTERACTIVE is defined") - Assert.True(completion.Contains "B", "Completion list should contain B because DEBUG is not defined") - - - /// FEATURE: Removing a #r into a file will cause it to no longer be seen by intellisense. - [] - member public this.``Fsx.HashR.Removed``() = - let code = - [ - "#r \"System.Transactions.dll\"" // Pick anything that isn't in the standard set of assemblies. - "open System.Transactions" - ] - let (project, file) = createSingleFileFsxFromLines code - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - ReplaceFileInMemory file - [ - "//#r \"System.Transactions.dll\"" // <-- Comment this line - "open System.Transactions" - ] - SaveFileToDisk(file) - TakeCoffeeBreak(this.VS) - VerifyErrorListContainedExpectedStr("Transactions",project) - gpatcc.AssertExactly(notAA[file], notAA[file], true (* expectCreate, because dependent DLL set changed *)) - - - - // Corecursive load to existing property. - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad3``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.Property" - ]) - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad9``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - "Namespace.Foo.Property" - ]) - let script1 = OpenFile(project,"Script1.fsx") - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected at second #load level (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad10``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected when dispersed between two #load levels (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad11``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected when dispersed between two #load levels (the other way) (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad12``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fsi\"" - "#load \"Script1.fsx\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertNoErrorsOrWarnings(project) - - // #nowarn seen in closed .fsx is global to the closure - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad16``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let thisProject = AddFileFromText(project,"ThisProject.fsx", - ["#nowarn \"44\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"ThisProject.fsx\"" // Should bring in #nowarn "44" so we don't see this warning: - "[]" - "let fn x = 0" - "let y = fn 1" - ]) - - let script1 = OpenFile(project,"Script1.fsx") - MoveCursorToEndOfMarker(script1,"let y = f") - TakeCoffeeBreak(this.VS) - AssertExactlyOneErrorSeenContaining(project, "This construct is deprecated. x") // This is expected for langVersion >= 10.0 - - /// FEATURE: #r in .fsx to a .dll name works. - [] - member public this.``Fsx.NoError.HashR.DllWithNoPath``() = - let fileContent = """ - #r "System.Transactions.dll" - open System.Transactions""" - this.VerifyFSXNoErrorList(fileContent) - - - [] - // 'System' is in the default set. Make sure we can still resolve it. - member public this.``Fsx.NoError.HashR.BugDefaultReferenceFileIsAlsoResolved``() = - let fileContent = """ - #r "System" - """ - this.VerifyFSXNoErrorList(fileContent) - - [] - member public this.``Fsx.NoError.HashR.DoubleReference``() = - let fileContent = """ - #r "System" - #r "System" - """ - this.VerifyFSXNoErrorList(fileContent) - - [] - // 'CustomMarshalers' is loaded from the GAC _and_ it is available on XP and above. - member public this.``Fsx.NoError.HashR.ResolveFromGAC``() = - let fileContent = """ - #r "CustomMarshalers" - """ - this.VerifyFSXNoErrorList(fileContent) - - [] - member public this.``Fsx.NoError.HashR.ResolveFromFullyQualifiedPath``() = - let fullyqualifiepathtoddll = System.IO.Path.Combine( System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll" ) - let code = ["#r @\"" + fullyqualifiepathtoddll + "\""] - let (project, _) = createSingleFileFsxFromLines code - AssertNoErrorsOrWarnings(project) - - [] - member public this.``Fsx.NoError.HashR.RelativePath1``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"lib.fs", - ["module Lib" - "let X = 42" - ]) - - let bld = Build(project) - - let script1Dir = Path.Combine(ProjectDirectory(project), "ccc") - let script1Path = Path.Combine(script1Dir, "Script1.fsx") - let script2Dir = Path.Combine(ProjectDirectory(project), "aaa\\bbb") - let script2Path = Path.Combine(script2Dir, "Script2.fsx") - - Directory.CreateDirectory(script1Dir) |> ignore - Directory.CreateDirectory(script2Dir) |> ignore - File.Move(bld.ExecutableOutput, Path.Combine(ProjectDirectory(project), "aaa\\lib.exe")) - - let script1 = File.WriteAllLines(script1Path, - ["#load \"../aaa/bbb/Script2.fsx\"" - "printfn \"%O\" Lib.X" - ]) - let script2 = File.WriteAllLines(script2Path, - ["#r \"../lib.exe\"" - ]) - - let script1 = OpenFile(project, script1Path) - TakeCoffeeBreak(this.VS) - - MoveCursorToEndOfMarker(script1,"#load") - let ans = GetSquiggleAtCursor(script1) - AssertNoSquiggle(ans) - - [] - member public this.``Fsx.NoError.HashR.RelativePath2``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"lib.fs", - ["module Lib" - "let X = 42" - ]) - - let bld = Build(project) - - let script1Dir = Path.Combine(ProjectDirectory(project), "ccc") - let script1Path = Path.Combine(script1Dir, "Script1.fsx") - let script2Dir = Path.Combine(ProjectDirectory(project), "aaa") - let script2Path = Path.Combine(script2Dir, "Script2.fsx") - - Directory.CreateDirectory(script1Dir) |> ignore - Directory.CreateDirectory(script2Dir) |> ignore - File.Move(bld.ExecutableOutput, Path.Combine(ProjectDirectory(project), "aaa\\lib.exe")) - - let script1 = File.WriteAllLines(script1Path, - ["#load \"../aaa/Script2.fsx\"" - "printfn \"%O\" Lib.X" - ]) - let script2 = File.WriteAllLines(script2Path, - ["#r \"lib.exe\"" - ]) - - let script1 = OpenFile(project, script1Path) - TakeCoffeeBreak(this.VS) - - MoveCursorToEndOfMarker(script1,"#load") - let ans = GetSquiggleAtCursor(script1) - AssertNoSquiggle(ans) - - /// FEATURE: #load in an .fsx file will include that file in the 'build' of the .fsx. - [] - member public this.``Fsx.NoError.HashLoad.Simple``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - [ - "namespace MyNamespace" - " module MyModule =" - " let x = 1" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ]) - let fsx = OpenFile(project,"File2.fsx") - AssertNoErrorsOrWarnings(project) - - // In this bug the #loaded file contains a level-4 warning (copy to avoid mutation). This warning was reported at the #load in file2.fsx but shouldn't have been.s - [] - member public this.``Fsx.NoWarn.OnLoadedFile.Bug4837``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - ["module File1Module" - "let x = System.DateTime.Now - System.DateTime.Now" - "x.Add(x) |> ignore" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - ]) - let fsx = OpenFile(project,"File2.fsx") - AssertNoErrorsOrWarnings(project) - - /// FEATURE: .fsx files have automatic imports of certain system assemblies. - //There is a test bug here. The actual scenario works. Need to revisit. - [] - member public this.``Fsx.NoError.AutomaticImportsForFsxFiles``() = - let fileContent = """ - open System - open System.Xml - open System.Drawing - open System.Runtime.Remoting - open System.Runtime.Serialization.Formatters.Soap - open System.Data - open System.Drawing - open System.Web - open System.Web.Services - open System.Windows.Forms""" - this.VerifyFSXNoErrorList(fileContent) - - // Corecursive load to nonexisting property. - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad4``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.NonExistingProperty" - ]) - let script1 = OpenFile(project,"Script1.fsx") - AssertExactlyOneErrorSeenContaining(project, "NonExistingProperty") - - // #load of .fsi is respected - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad5``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - "Namespace.Foo.HiddenProperty" - ]) - let script1 = OpenFile(project,"Script1.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // #load of .fsi is respected at second #load level - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad6``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "Namespace.Foo.HiddenProperty" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // #load of .fsi is respected when dispersed between two #load levels - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad7``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.HiddenProperty" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // #load of .fsi is respected when dispersed between two #load levels (the other way) - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad8``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fsi\"" - "#load \"Script1.fsx\"" - "Namespace.Foo.HiddenProperty" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // Bug seen during development: A #load in an .fs would be followed. - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad15``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file2 = AddFileFromText(project,"File2.fs", - ["namespace Namespace" - "type Type() =" - " static member Property = 0" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["#load \"File2.fs\"" // This is not allowed but it was working anyway. - "namespace File2Namespace" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fs\"" - "Namespace.Type.Property" - ]) - - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - AssertExactlyOneErrorSeenContaining(project, "Namespace") - - [] - member public this.``Fsx.Bug4311HoverOverReferenceInFirstLine``() = - let fileContent = """#r "PresentationFramework.dll" - - #r "PresentationCore.dll" """ - let marker = "#r \"PresentationFrame" - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker "PresentationFramework.dll" - this.AssertQuickInfoNotContainsAtEndOfMarkerInFsxFile fileContent marker "multiple results" - - [] - member public this.``Fsx.QuickInfo.Bug4979``() = - let code = - ["System.ConsoleModifiers.Shift |> ignore " - "(3).ToString().Length |> ignore "] - let (project, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file, "System.ConsoleModifiers.Sh") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip, @"The left or right SHIFT modifier key.") - - MoveCursorToEndOfMarker(file, "(3).ToString().Len") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip, @"[Signature:P:System.String.Length]") // A message from the mock IDocumentationBuilder - AssertContains(tooltip, @"[Filename:") - AssertContains(tooltip, @"netstandard.dll]") // The assembly we expect the documentation to get taken from - - // Especially under 4.0 we need #r of .NET framework assemblies to resolve from like, - // - // %program files%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0 - // - // because this is where the .XML files are. - // - // When executing scripts, however, we need to _not_ resolve from these directories because - // they may be metadata-only assemblies. - // - // "Reference Assemblies" was only introduced in 3.5sp1, so not all 2.0 F# boxes will have it, so only run on 4.0 - [] - member public this.``Fsx.Bug5073``() = - let fileContent = """#r "System" """ - let marker = "#r \"System" - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker @"Reference Assemblies\Microsoft" - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker ".NET Framework" - /// FEATURE: Hovering over a resolved #r file will show a data tip with the fully qualified path to that file. [] member public this.``Fsx.HashR_QuickInfo.ShowFilenameOfResolvedAssembly``() = @@ -906,290 +137,6 @@ type UsingMSBuild() as this = """#r "System.Transactions" """ // Pick anything that isn't in the standard set of assemblies. "#r \"System.Tra" "System.Transactions.dll" - [] - member public this.``Fsx.HashR_QuickInfo.BugDefaultReferenceFileIsAlsoResolved``() = - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile - """#r "System" """ // 'System' is in the default set. Make sure we can still resolve it. - "#r \"Syst" "System.dll" - - [] - member public this.``Fsx.HashR_QuickInfo.DoubleReference``() = - let fileContent = """#r "System" // Mark1 - #r "System" // Mark2 """ // The same reference repeated twice. - this.AssertQuickInfoContainsAtStartOfMarkerInFsxFile fileContent "tem\" // Mark1" "System.dll" - this.AssertQuickInfoContainsAtStartOfMarkerInFsxFile fileContent "tem\" // Mark2" "System.dll" - - [] - member public this.``Fsx.HashR_QuickInfo.ResolveFromGAC``() = - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile - """#r "CustomMarshalers" """ // 'mscorcfg' is loaded from the GAC _and_ it is available on XP and above. - "#r \"Custo" ".NET Framework" - - [] - member public this.``Fsx.HashR_QuickInfo.ResolveFromFullyQualifiedPath``() = - let fullyqualifiepathtoddll = System.IO.Path.Combine( System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll" ) // Can be any fully qualified path to an assembly - let expectedtooltip = System.Reflection.Assembly.ReflectionOnlyLoadFrom(fullyqualifiepathtoddll).FullName - let fileContent = "#r @\"" + fullyqualifiepathtoddll + "\"" - let marker = "#r @\"" + fullyqualifiepathtoddll.Substring(0,fullyqualifiepathtoddll.Length/2) // somewhere in the middle of the string - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker expectedtooltip - //this.AssertQuickInfoNotContainsAtEndOfMarkerInFsxFile fileContent marker ".dll" - - [] - member public this.``Fsx.InvalidHashReference.ShouldBeASquiggle.Bug3012``() = - let code = ["#r \"Bar.dll\""] - let (project, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"#r \"Ba") - let squiggle = GetSquiggleAtCursor(file) - TakeCoffeeBreak(this.VS) - Assert.True(snd squiggle.Value |> fun str -> str.Contains("Bar.dll")) - - // Bug seen during development: The unresolved reference error would x-ray through to the root. - [] - member public this.``Fsx.ScriptClosure.TransitiveLoad14``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#r \"NonExisting\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "#r \"System\"" - ]) - - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - MoveCursorToEndOfMarker(script1,"#r \"Sys") - AssertEqual(None,GetSquiggleAtCursor(script1)) - - member private this.TestFsxHashDirectivesAreErrors(mark : string, expectedStr : string) = - let code = - [ - "#r \"JoeBob\"" - "#I \".\"" - "#load \"Dooby\"" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,mark) - let ans = GetSquiggleAtCursor(file) - match ans with - | Some(sev,msg) -> - AssertEqual(Microsoft.VisualStudio.FSharp.LanguageService.Severity.Error, sev) - AssertContains(msg, expectedStr) - | _ -> failwith "" - - /// FEATURE: #r, #I, #load are all errors when running under the language service - [] - member public this.``Fsx.HashDirectivesAreErrors.InNonScriptFiles.Case1``() = - this.TestFsxHashDirectivesAreErrors("#r \"Joe", "may only be used in F# script files") - - [] - member public this.``Fsx.HashDirectivesAreErrors.InNonScriptFiles.Case2``() = - this.TestFsxHashDirectivesAreErrors("#I \"", "may only be used in F# script files") - - [] - member public this.``Fsx.HashDirectivesAreErrors.InNonScriptFiles.Case3``() = - this.TestFsxHashDirectivesAreErrors("#load \"Doo", "may only be used in F# script files") - - /// FEATURE: #reference against a non-assembly .EXE gives a reasonable error message - //[] - member public this.``Fsx.HashReferenceAgainstNonAssemblyExe``() = - let windows = System.Environment.GetEnvironmentVariable("windir") - let code = - [ - sprintf "#reference @\"%s\"" (Path.Combine(windows,"notepad.exe")) - " let x = 1"] - let (_, file) = createSingleFileFsxFromLines code - - MoveCursorToEndOfMarker(file,"#refe") - let ans = GetSquiggleAtCursor(file) - AssertSquiggleIsErrorContaining(ans, "was not found or is invalid") - - (* ---------------------------------------------------------------------------------- *) - - // FEATURE: A #loaded file is squiggled with an error if there are errors in that file. - [] - member public this.``Fsx.HashLoadedFileWithErrors.Bug3149``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - - let file1 = AddFileFromText(project,"File1.fs", - [ - "module File1" - "DogChow" // <-- error - ]) - - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#load @\"File1.fs\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#load @\"Fi") - TakeCoffeeBreak(this.VS) - let ans = GetSquiggleAtCursor(file2) - AssertSquiggleIsErrorContaining(ans, "DogChow") - - - // FEATURE: A #loaded file is squiggled with a warning if there are warning that file. - [] - member public this.``Fsx.HashLoadedFileWithWarnings.Bug3149``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - - let file1 = AddFileFromText(project,"File1.fs", - ["module File1Module" - "type WarningHere<'a> = static member X() = 0" - "let y = WarningHere.X" - ]) - - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#load @\"File1.fs\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#load @\"Fi") - let ans = GetSquiggleAtCursor(file2) - AssertSquiggleIsWarningContaining(ans, "WarningHere") - - // Bug: #load should report the first error message from a file - [] - member public this.``Fsx.HashLoadedFileWithErrors.Bug3652``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - - let file1 = AddFileFromText(project,"File1.fs", - [ - "module File1" - "let a = 1 + \"\"" - "let c = new obj()" - "let b = c.foo()" - ]) - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#load @\"File1.fs\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#load @\"Fi") - let ans = GetSquiggleAtCursor(file2) - AssertSquiggleIsErrorContaining(ans, "'string'") - AssertSquiggleIsErrorContaining(ans, "'int'") - AssertSquiggleIsErrorNotContaining(ans, "foo") - - // In this bug the .fsx project directory was wrong so it couldn't reference a relative file. - [] - member public this.``Fsx.ScriptCanReferenceBinDirectoryOutput.Bug3151``() = - use _guard = this.UsingNewVS() - let stopWatch = new System.Diagnostics.Stopwatch() - let ResetStopWatch() = stopWatch.Reset(); stopWatch.Start() - let time1 op a message = - ResetStopWatch() - let result = op a - printf "%s %d ms\n" message stopWatch.ElapsedMilliseconds - result - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", []) - let projectOutput = time1 Build project "Time to build project" - printfn "Output of building project was %s" projectOutput.ExecutableOutput - printfn "Project directory is %s" (ProjectDirectory project) - - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#reference @\"bin\\Debug\\testproject.exe\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#reference @\"bin\\De") - let ans = GetSquiggleAtCursor(file2) - AssertNoSquiggle(ans) - - - - /// In this bug, multiple references to mscorlib .dll were causing problem in load closure - [] - member public this.``Fsx.BugAllowExplicitReferenceToMsCorlib``() = - let code = - ["#r \"mscorlib\"" - "fsi." - ] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"fsi.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"CommandLineArgs") - - /// FEATURE: There is a global fsi module that should be in scope for script files. - [] - member public this.``Fsx.Bug2530FsiObject``() = - let code = - [ - "fsi." - ] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"fsi.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"CommandLineArgs") - - // Ensure that the script closure algorithm gets the right order of hash directives - [] - member public this.``Fsx.ScriptClosure.SurfaceOrderOfHashes``() = - let code = - ["#r \"System.Runtime.Remoting\"" - "#r \"System.Transactions\"" - "#load \"Load1.fs\"" - "#load \"Load2.fsx\"" - ] - let (project, file) = createSingleFileFsxFromLines code - let projectFolder = ProjectDirectory(project) - let fas = GetProjectOptionsOfScript(file) - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "--noframework") - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "System.Runtime.Remoting.dll") - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "System.Transactions.dll") - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "FSharp.Compiler.Interactive.Settings.dll") - Assert.Equal(Path.Combine(projectFolder,"File1.fsx"), fas.SourceFiles.[0]) - Assert.Equal(1, fas.SourceFiles.Length) - - - /// FEATURE: #reference against a strong name should work. - [] - member public this.``Fsx.HashReferenceAgainstStrongName``() = - let code = - [ - sprintf "#reference \"System.Core, Version=%s, Culture=neutral, PublicKeyToken=b77a5c561934e089\"" (System.Environment.Version.ToString()) - "open System."] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"open System.") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Linq") - - - /// Try out some bogus file names in #r, #I and #load. - [] - member public this.``Fsx.InvalidMetaCommandFilenames``() = - let code = - [ - "#r @\"\"" - "#load @\"\"" - "#I @\"\"" - "#r @\"*\"" - "#load @\"*\"" - "#I @\"*\"" - "#r @\"?\"" - "#load @\"?\"" - "#I @\"?\"" - """#r @"C:\path\does\not\exist.dll" """ - ] - let (_, file) = createSingleFileFsxFromLines code - TakeCoffeeBreak(this.VS) // This used to assert - /// FEATURE: .fsx files have INTERACTIVE #defined [] member public this.``Fsx.INTERACTIVEIsDefinedInFsxFiles``() = @@ -1423,76 +370,6 @@ type UsingMSBuild() as this = Assert.True(not(build.BuildSucceeded), "Expected build to fail") - /// There was a problem in which synthetic tokens like #load were causing asserts - [] - member public this.``Fsx.SyntheticTokens``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#r \"\"" - "#reference \"\"" - "#load \"\"" - "#line 52" - "#nowarn 72"] - ) - - /// There was a problem where an unclosed reference picked up the text of the reference on the next line. - [] - member public this.``Fsx.ShouldBeAbleToReference30Assemblies.Bug2050``() = - let code = - [ - "#r \"System.Core.dll\"" - "open System." - ] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"open System.") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Linq") - - /// There was a problem where an unclosed reference picked up the text of the reference on the next line. - [] - member public this.``Fsx.UnclosedHashReference.Case1``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#reference \"" // Unclosed - "#reference \"Hello There\""] - ) - [] - member public this.``Fsx.UnclosedHashReference.Case2``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#r \"" // Unclosed - "# \"Hello There\""] - ) - - /// There was a problem where an unclosed reference picked up the text of the reference on the next line. - [] - member public this.``Fsx.UnclosedHashLoad``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#load \"" // Unclosed - "#load \"Hello There\""] - ) - - [] - member public this.``TypeProvider.UnitsOfMeasure.SmokeTest1``() = - let code = - ["open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames" - "let x : System.Nullable> = N1.T1.MethodWithTypesInvolvingUnitsOfMeasure(1.0)" - "let x2 : int = N1.T1().MethodWithErasedCodeUsingConditional()" - "let x3 : int = N1.T1().MethodWithErasedCodeUsingTypeAs()" - ] - let refs = - [ - PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll") - ] - let (_, project, file) = this.CreateSingleFileProject(code, references = refs) - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - member public this.TypeProviderDisposalSmokeTest(clearing) = use _guard = this.UsingNewVS() let providerAssemblyName = PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")