diff --git a/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj b/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj
index 535a4a590be..5b035b3c9fc 100644
--- a/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj
+++ b/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj
@@ -81,6 +81,7 @@
FSStrings.resx
+ FSStrings.resources
--module Microsoft.FSharp.Compiler.AbstractIL.Internal.AsciiParser --open Microsoft.FSharp.Compiler.AbstractIL --internal --lexlib Internal.Utilities.Text.Lexing --parslib Internal.Utilities.Text.Parsing
diff --git a/src/fsharp/import.fs b/src/fsharp/import.fs
index dab3e6eec93..6db631a0318 100644
--- a/src/fsharp/import.fs
+++ b/src/fsharp/import.fs
@@ -4,6 +4,7 @@
module internal Microsoft.FSharp.Compiler.Import
open System.Reflection
+open System.Collections.Concurrent
open System.Collections.Generic
open Microsoft.FSharp.Compiler.AbstractIL.IL
@@ -52,7 +53,7 @@ type AssemblyLoader =
/// serves as an interface through to the tables stored in the primary TcImports structures defined in CompileOps.fs.
[]
type ImportMap(g:TcGlobals,assemblyLoader:AssemblyLoader) =
- let typeRefToTyconRefCache = new System.Collections.Generic.Dictionary()
+ let typeRefToTyconRefCache = ConcurrentDictionary()
member this.g = g
member this.assemblyLoader = assemblyLoader
member this.ILTypeRefToTyconRefCache = typeRefToTyconRefCache
diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs
index 0028b767202..3fd19dacfe5 100755
--- a/src/fsharp/service/IncrementalBuild.fs
+++ b/src/fsharp/service/IncrementalBuild.fs
@@ -1698,14 +1698,16 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput
/// CreateIncrementalBuilder (for background type checking). Note that fsc.fs also
/// creates an incremental builder used by the command line compiler.
static member TryCreateBackgroundBuilderForProjectOptions (ctok, legacyReferenceResolver, defaultFSharpBinariesDir, frameworkTcImportsCache: FrameworkImportsCache, loadClosureOpt:LoadClosure option, sourceFiles:string list, commandLineArgs:string list, projectReferences, projectDirectory, useScriptResolutionRules, keepAssemblyContents, keepAllBackgroundResolutions, maxTimeShareMilliseconds) =
- let targetProfileSwitch = "--targetprofile:"
let useSimpleResolutionSwitch = "--simpleresolution"
cancellable {
// Trap and report warnings and errors from creation.
- use errorScope = new ErrorScope()
- let! builderOpt =
+ let delayedLogger = CapturingErrorLogger("IncrementalBuilderCreation")
+ use _unwindEL = PushErrorLoggerPhaseUntilUnwind (fun _ -> delayedLogger)
+ use _unwindBP = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter
+
+ let! builderOpt =
cancellable {
try
@@ -1741,22 +1743,12 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput
#else
tcConfigB.useSimpleResolution <- (getSwitchValue useSimpleResolutionSwitch) |> Option.isSome
#endif
- match (getSwitchValue targetProfileSwitch) with
- | Some v ->
- let _s = v
- CompileOptions.SetTargetProfile tcConfigB v
- | None -> ()
-
// Apply command-line arguments and collect more source files if they are in the arguments
let sourceFilesNew = ApplyCommandLineArgs(tcConfigB, sourceFiles, commandLineArgs)
// Never open PDB files for the language service, even if --standalone is specified
tcConfigB.openDebugInformationForLaterStaticLinking <- false
- match commandLineArgs |> Seq.tryFind(fun s -> s.StartsWith(targetProfileSwitch)) with
- | Some arg ->
- let profile = arg.Substring(targetProfileSwitch.Length)
- CompileOptions.SetTargetProfile tcConfigB profile
- | _ -> ()
+
tcConfigB, sourceFilesNew
match loadClosureOpt with
@@ -1825,7 +1817,18 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput
return None
}
- return builderOpt, errorScope.Diagnostics
+ let diagnostics =
+ match builderOpt with
+ | Some builder ->
+ let errorSeverityOptions = builder.TcConfig.errorSeverityOptions
+ let errorLogger = CompilationErrorLogger("IncrementalBuilderCreation", errorSeverityOptions)
+ delayedLogger.CommitDelayedDiagnostics(errorLogger)
+ errorLogger.GetErrors() |> List.map (fun (d, severity) -> d, severity = FSharpErrorSeverity.Error)
+ | _ ->
+ delayedLogger.Diagnostics
+ |> List.map (fun (d, isError) -> FSharpErrorInfo.CreateFromException(d, isError, range.Zero))
+
+ return builderOpt, diagnostics
}
static member KeepBuilderAlive (builderOpt: IncrementalBuilder option) =
match builderOpt with
diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs
index 935fbf25476..c13731306dd 100644
--- a/src/fsharp/symbols/SymbolHelpers.fs
+++ b/src/fsharp/symbols/SymbolHelpers.fs
@@ -150,15 +150,14 @@ type internal CompilationErrorLogger (debugName: string, options: FSharpErrorSev
override x.DiagnosticSink(exn, isError) =
if isError || ReportWarningAsError options exn then
- diagnostics.Add(exn, isError)
+ diagnostics.Add(exn, FSharpErrorSeverity.Error)
errorCount <- errorCount + 1
else if ReportWarning options exn then
- diagnostics.Add(exn, isError)
+ diagnostics.Add(exn, FSharpErrorSeverity.Warning)
override x.ErrorCount = errorCount
- member x.GetErrors() =
- [ for (e, isError) in diagnostics -> e, (if isError then FSharpErrorSeverity.Error else FSharpErrorSeverity.Warning) ]
+ member x.GetErrors() = List.ofSeq diagnostics
/// This represents the global state established as each task function runs as part of the build.
diff --git a/tests/service/Common.fs b/tests/service/Common.fs
index 8b76fa107c7..d038ff178a1 100644
--- a/tests/service/Common.fs
+++ b/tests/service/Common.fs
@@ -160,6 +160,23 @@ let mkProjectCommandLineArgsForScript (dllName, fileNames) =
|]
#endif
+let mkTestFileAndOptions source additionalArgs =
+ let fileName = Path.ChangeExtension(Path.GetTempFileName(), ".fs")
+ let project = Path.GetTempFileName()
+ let dllName = Path.ChangeExtension(project, ".dll")
+ let projFileName = Path.ChangeExtension(project, ".fsproj")
+ let fileSource1 = "module M"
+ File.WriteAllText(fileName, fileSource1)
+
+ let args = Array.append (mkProjectCommandLineArgs (dllName, [fileName])) additionalArgs
+ let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args)
+ fileName, options
+
+let parseAndCheckFile fileName source options =
+ match checker.ParseAndCheckFileInProject(fileName, 0, source, options) |> Async.RunSynchronously with
+ | parseResults, FSharpCheckFileAnswer.Succeeded(checkResults) -> parseResults, checkResults
+ | _ -> failwithf "Parsing aborted unexpectedly..."
+
let parseAndCheckScript (file, input) =
#if DOTNETCORE
diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs
index 6cf1795c1cf..93463d6a203 100644
--- a/tests/service/ProjectAnalysisTests.fs
+++ b/tests/service/ProjectAnalysisTests.fs
@@ -5195,3 +5195,16 @@ type A(i:int) =
| Some decl -> failwithf "unexpected declaration %A" decl
| None -> failwith "declaration list is empty"
+
+
+[]
+[]
+[]
+[]
+[]
+let ``#4030, Incremental builder creation warnings`` (args, errorSeverities) =
+ let source = "module M"
+ let fileName, options = mkTestFileAndOptions source args
+
+ let _, checkResults = parseAndCheckFile fileName source options
+ checkResults.Errors |> Array.map (fun e -> e.Severity = FSharpErrorSeverity.Error) |> shouldEqual errorSeverities
diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs
index ee47b94e085..b5da2f6bb24 100644
--- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs
+++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs
@@ -85,10 +85,9 @@ type internal FSharpCompletionProvider
else
let triggerPosition = caretPosition - 1
let triggerChar = sourceText.[triggerPosition]
- let prevChar = sourceText.[triggerPosition - 1]
-
+
// do not trigger completion if it's not single dot, i.e. range expression
- if not Settings.IntelliSense.ShowAfterCharIsTyped && prevChar = '.' then
+ if not Settings.IntelliSense.ShowAfterCharIsTyped && triggerPosition > 0 && sourceText.[triggerPosition - 1] = '.' then
false
else
let documentId, filePath, defines = getInfo()
diff --git a/vsintegration/tests/unittests/CompletionProviderTests.fs b/vsintegration/tests/unittests/CompletionProviderTests.fs
index 6a6c64f44b1..5e0212f62bd 100644
--- a/vsintegration/tests/unittests/CompletionProviderTests.fs
+++ b/vsintegration/tests/unittests/CompletionProviderTests.fs
@@ -273,6 +273,18 @@ xVal**y
let triggered = FSharpCompletionProvider.ShouldTriggerCompletionAux(SourceText.From(fileContents), caretPosition, CompletionTriggerKind.Insertion, getInfo)
Assert.IsTrue(triggered, "Completion should trigger after typing an identifier that follows a mathematical operation")
+[]
+let ShouldTriggerCompletionAtStartOfFileWithInsertion =
+ let fileContents = """
+l"""
+
+ let marker = "l"
+ let caretPosition = fileContents.IndexOf(marker) + marker.Length
+ let documentId = DocumentId.CreateNewId(ProjectId.CreateNewId())
+ let getInfo() = documentId, filePath, []
+ let triggered = FSharpCompletionProvider.ShouldTriggerCompletionAux(SourceText.From(fileContents), caretPosition, CompletionTriggerKind.Insertion, getInfo)
+ Assert.IsTrue(triggered, "Completion should trigger after typing an Insertion character at the top of the file, e.g. a function definition in a new script file.")
+
[]
let ShouldDisplayTypeMembers() =
let fileContents = """