diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index ab20bfcf139..711825ddef2 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2321,6 +2321,7 @@ type TcConfigBuilder = isInvalidationSupported = isInvalidationSupported copyFSharpCore = defaultCopyFSharpCore tryGetMetadataSnapshot = tryGetMetadataSnapshot + useFsiAuxLib = isInteractive } member tcConfigB.ResolveSourceFile(m, nm, pathLoadedFrom) = diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 774fd78e108..e812814d054 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1731,7 +1731,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput defaultFSharpBinariesDir, implicitIncludeDir=projectDirectory, reduceMemoryUsage=ReduceMemoryFlag.Yes, - isInteractive=false, + isInteractive=useScriptResolutionRules, isInvalidationSupported=true, defaultCopyFSharpCore=CopyFSharpCoreFlag.No, tryGetMetadataSnapshot=tryGetMetadataSnapshot) diff --git a/tests/service/ExprTests.fs b/tests/service/ExprTests.fs index f2215974b95..bbd3d7e09a3 100644 --- a/tests/service/ExprTests.fs +++ b/tests/service/ExprTests.fs @@ -1060,7 +1060,7 @@ let ``Test Operator Declarations for Byte`` () = "let testByteToDecimalOperator(e1) = Convert.ToDecimal (e1) @ (54,43--54,53)"; "let testByteToCharOperator(e1) = Operators.ToChar (e1) @ (55,43--55,50)"; "let testByteToStringOperator(e1) = let matchValue: Microsoft.FSharp.Core.obj = Operators.Box (e1) in match (if Operators.op_Equality (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ... @ (56,43--56,52)"; - ] + ] testOperators "Byte" "byte" excludedTests expectedUnoptimized expectedOptimized diff --git a/vsintegration/tests/UnitTests/FsxCompletionProviderTests.fs b/vsintegration/tests/UnitTests/FsxCompletionProviderTests.fs new file mode 100644 index 00000000000..ec678dece7d --- /dev/null +++ b/vsintegration/tests/UnitTests/FsxCompletionProviderTests.fs @@ -0,0 +1,136 @@ + +// To run the tests in this file: +// +// Technique 1: Compile VisualFSharp.UnitTests.dll and run it as a set of unit tests +// +// Technique 2: +// +// Enable some tests in the #if EXE section at the end of the file, +// then compile this file as an EXE that has InternalsVisibleTo access into the +// appropriate DLLs. This can be the quickest way to get turnaround on updating the tests +// and capturing large amounts of structured output. +(* + cd Debug\net40\bin + .\fsc.exe --define:EXE -r:.\Microsoft.Build.Utilities.Core.dll -o VisualFSharp.UnitTests.exe -g --optimize- -r .\FSharp.Compiler.Private.dll -r .\FSharp.Editor.dll -r nunit.framework.dll ..\..\..\tests\service\FsUnit.fs ..\..\..\tests\service\Common.fs /delaysign /keyfile:..\..\..\src\fsharp\msft.pubkey ..\..\..\vsintegration\tests\UnitTests\FsxCompletionProviderTests.fs + .\VisualFSharp.UnitTests.exe +*) +// Technique 3: +// +// Use F# Interactive. This only works for FSharp.Compiler.Service.dll which has a public API + +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +module Microsoft.VisualStudio.FSharp.Editor.Tests.Roslyn.FsxCompletionProviderTests + +open System +open System.Linq + +open NUnit.Framework + +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.Completion +open Microsoft.CodeAnalysis.Text +open Microsoft.VisualStudio.FSharp.Editor + +open FSharp.Compiler.SourceCodeServices +open UnitTests.TestLib.LanguageService + +let filePath = "C:\\test.fsx" +let internal projectOptions = { + ProjectFileName = "C:\\test.fsproj" + ProjectId = None + SourceFiles = [| filePath |] + ReferencedProjects = [| |] + OtherOptions = [| |] + IsIncompleteTypeCheckEnvironment = true + UseScriptResolutionRules = true + LoadTime = DateTime.MaxValue + OriginalLoadReferences = [] + UnresolvedReferences = None + ExtraProjectInfo = None + Stamp = None +} + +let formatCompletions(completions : string seq) = + "\n\t" + String.Join("\n\t", completions) + +let VerifyCompletionList(fileContents: string, marker: string, expected: string list, unexpected: string list) = + let caretPosition = fileContents.IndexOf(marker) + marker.Length + let results = + FSharpCompletionProvider.ProvideCompletionsAsyncAux(checker, SourceText.From(fileContents), caretPosition, projectOptions, filePath, 0, (fun _ -> []), LanguageServicePerformanceOptions.Default, IntelliSenseOptions.Default) + |> Async.RunSynchronously + |> Option.defaultValue (ResizeArray()) + |> Seq.map(fun result -> result.DisplayText) + + let expectedFound = + expected + |> Seq.filter results.Contains + + let expectedNotFound = + expected + |> Seq.filter (expectedFound.Contains >> not) + + let unexpectedNotFound = + unexpected + |> Seq.filter (results.Contains >> not) + + let unexpectedFound = + unexpected + |> Seq.filter (unexpectedNotFound.Contains >> not) + + // If either of these are true, then the test fails. + let hasExpectedNotFound = not (Seq.isEmpty expectedNotFound) + let hasUnexpectedFound = not (Seq.isEmpty unexpectedFound) + + if hasExpectedNotFound || hasUnexpectedFound then + let expectedNotFoundMsg = + if hasExpectedNotFound then + sprintf "\nExpected completions not found:%s\n" (formatCompletions expectedNotFound) + else + String.Empty + + let unexpectedFoundMsg = + if hasUnexpectedFound then + sprintf "\nUnexpected completions found:%s\n" (formatCompletions unexpectedFound) + else + String.Empty + + let completionsMsg = sprintf "\nin Completions:%s" (formatCompletions results) + + let msg = sprintf "%s%s%s" expectedNotFoundMsg unexpectedFoundMsg completionsMsg + + Assert.Fail(msg) + +let VerifyCompletionListExactly(fileContents: string, marker: string, expected: string list) = + let caretPosition = fileContents.IndexOf(marker) + marker.Length + + let actual = + let x = FSharpCompletionProvider.ProvideCompletionsAsyncAux(checker, SourceText.From(fileContents), caretPosition, projectOptions, filePath, 0, (fun _ -> []), LanguageServicePerformanceOptions.Default, IntelliSenseOptions.Default) + |> Async.RunSynchronously + x |> Option.defaultValue (ResizeArray()) + |> Seq.toList + // sort items as Roslyn do - by `SortText` + |> List.sortBy (fun x -> x.SortText) + + let actualNames = actual |> List.map (fun x -> x.DisplayText) + + if actualNames <> expected then + Assert.Fail(sprintf "Expected:\n%s,\nbut was:\n%s\nactual with sort text:\n%s" + (String.Join("; ", expected |> List.map (sprintf "\"%s\""))) + (String.Join("; ", actualNames |> List.map (sprintf "\"%s\""))) + (String.Join("\n", actual |> List.map (fun x -> sprintf "%s => %s" x.DisplayText x.SortText)))) + +[] +let ShouldTriggerCompletionInFsxFile() = + let fileContents = """ +fsi. +""" + let expected = ["CommandLineArgs"; "EventLoop"; "FloatingPointFormat"; "FormatProvider"; "PrintDepth"; + "PrintLength"; "PrintSize"; "PrintWidth"; "ShowDeclarationValues"; "ShowIEnumerable"; + "ShowProperties"; "AddPrinter"; "AddPrintTransformer"; "Equals"; "GetHashCode"; + "GetType"; "ToString"; ] + VerifyCompletionListExactly(fileContents, "fsi.", expected) + + +#if EXE +ShouldTriggerCompletionInFsxFile() +#endif diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 6a3cae016a6..9598b23b5c2 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -148,6 +148,9 @@ Roslyn\CompletionProviderTests.fs + + Roslyn\FsxCompletionProviderTests.fs + Roslyn\SignatureHelpProviderTests.fs