From 899ad91506abfcf37dbd50eb553c81730af60286 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 23 Nov 2016 13:08:21 +0000 Subject: [PATCH 1/2] Fix 1805,1807 --- src/fsharp/CompileOps.fs | 1 + src/fsharp/FSStrings.resx | 3 +++ .../src/FSharp.Editor/BreakpointResolutionService.fs | 9 ++++----- vsintegration/src/FSharp.Editor/CompletionProvider.fs | 9 ++++++--- vsintegration/src/FSharp.Editor/GoToDefinitionService.fs | 7 ++++--- .../src/FSharp.Editor/LanguageDebugInfoService.fs | 4 +++- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index b1dcc1c77a5..91dc03a6482 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -992,6 +992,7 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) = | Parser.TOKEN_KEYWORD_STRING -> getErrorString("Parser.TOKEN.KEYWORD_STRING") | Parser.TOKEN_EOF -> getErrorString("Parser.TOKEN.EOF") | Parser.TOKEN_CONST -> getErrorString("Parser.TOKEN.CONST") + | Parser.TOKEN_FIXED -> getErrorString("Parser.TOKEN.FIXED") | unknown -> System.Diagnostics.Debug.Assert(false,"unknown token tag") let result = sprintf "%+A" unknown diff --git a/src/fsharp/FSStrings.resx b/src/fsharp/FSStrings.resx index 04bce992367..9dd1eef5577 100644 --- a/src/fsharp/FSStrings.resx +++ b/src/fsharp/FSStrings.resx @@ -447,6 +447,9 @@ keyword 'internal' + + keyword 'fixed' + keyword 'constraint' diff --git a/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs b/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs index c50ae6cba46..3aa4f907744 100644 --- a/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs +++ b/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs @@ -33,12 +33,11 @@ type internal FSharpBreakpointResolutionService() = static member GetBreakpointLocation(sourceText: SourceText, fileName: string, textSpan: TextSpan, options: FSharpProjectOptions) = async { let! parseResults = FSharpChecker.Instance.ParseFileInProject(fileName, sourceText.ToString(), options) - let textLine = sourceText.Lines.GetLineFromPosition(textSpan.Start) + let textLinePos = sourceText.Lines.GetLinePosition(textSpan.Start) + let textLineColumn = textLinePos.Character + let fcsTextLineNumber = textLinePos.Line + 1 // Roslyn line numbers are zero-based, FSharp.Compiler.Service line numbers are 1-based - let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based - let textColumnNumber = textSpan.Start - textLine.Start - - return parseResults.ValidateBreakpointLocation(mkPos textLineNumber textColumnNumber) + return parseResults.ValidateBreakpointLocation(mkPos fcsTextLineNumber textLineColumn) } interface IBreakpointResolutionService with diff --git a/vsintegration/src/FSharp.Editor/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/CompletionProvider.fs index 3c5c8878b34..1c7aec7f95a 100644 --- a/vsintegration/src/FSharp.Editor/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/CompletionProvider.fs @@ -80,9 +80,12 @@ type internal FSharpCompletionProvider(workspace: Workspace, serviceProvider: SV | FSharpCheckFileAnswer.Succeeded(results) -> results let textLine = sourceText.Lines.GetLineFromPosition(caretPosition) - let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based - let qualifyingNames, partialName = QuickParse.GetPartialLongNameEx(textLine.ToString(), caretPosition - textLine.Start - 1) - let! declarations = checkFileResults.GetDeclarationListInfo(Some(parseResults), textLineNumber, caretPosition, textLine.ToString(), qualifyingNames, partialName) + let textLinePos = sourceText.Lines.GetLinePosition(caretPosition) + let fcsTextLineNumber = textLinePos.Line + 1 // Roslyn line numbers are zero-based, FSharp.Compiler.Service line numbers are 1-based + let textLineColumn = textLinePos.Character + + let qualifyingNames, partialName = QuickParse.GetPartialLongNameEx(textLine.ToString(), textLineColumn - 1) + let! declarations = checkFileResults.GetDeclarationListInfo(Some(parseResults), fcsTextLineNumber, textLineColumn, textLine.ToString(), qualifyingNames, partialName) let results = List() diff --git a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs index 62bc7bfd47b..a839f6c9721 100644 --- a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs @@ -54,8 +54,9 @@ type internal FSharpGoToDefinitionService [] ([> = async { let textLine = sourceText.Lines.GetLineFromPosition(position) - let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based - let textLineColumn = sourceText.Lines.GetLinePosition(position).Character + let textLinePos = sourceText.Lines.GetLinePosition(position) + let fcsTextLineNumber = textLinePos.Line + 1 // Roslyn line numbers are zero-based, FSharp.Compiler.Service line numbers are 1-based + let textLineColumn = textLinePos.Character let classifiedSpanOption = FSharpColorizationService.GetColorizationData(sourceText, textLine.Span, Some(filePath), defines, cancellationToken) |> Seq.tryFind(fun classifiedSpan -> classifiedSpan.TextSpan.Contains(position)) @@ -67,7 +68,7 @@ type internal FSharpGoToDefinitionService [] ([ failwith "Compilation isn't complete yet" | FSharpCheckFileAnswer.Succeeded(results) -> results - let! declarations = checkFileResults.GetDeclarationLocationAlternate (textLineNumber, islandColumn, textLine.ToString(), qualifiers, false) + let! declarations = checkFileResults.GetDeclarationLocationAlternate (fcsTextLineNumber, islandColumn, textLine.ToString(), qualifiers, false) return match declarations with | FSharpFindDeclResult.DeclFound(range) -> Some(range) diff --git a/vsintegration/src/FSharp.Editor/LanguageDebugInfoService.fs b/vsintegration/src/FSharp.Editor/LanguageDebugInfoService.fs index bba0ecf6b5a..928988ce323 100644 --- a/vsintegration/src/FSharp.Editor/LanguageDebugInfoService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageDebugInfoService.fs @@ -46,7 +46,9 @@ type internal FSharpLanguageDebugInfoService() = | ClassificationTypeNames.Identifier -> let textLine = sourceText.Lines.GetLineFromPosition(position) - match QuickParse.GetCompleteIdentifierIsland false (textLine.ToString()) (position - textLine.Start) with + let textLinePos = sourceText.Lines.GetLinePosition(position) + let textLineColumn = textLinePos.Character + match QuickParse.GetCompleteIdentifierIsland false (textLine.ToString()) textLineColumn with | None -> None | Some(island, islandEnd, _) -> let islandDocumentStart = textLine.Start + islandEnd - island.Length From 2b5824ea6c91300406ee3e5041414a29d1b21508 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 23 Nov 2016 13:23:20 +0000 Subject: [PATCH 2/2] fix assert in goto-definition --- .../src/FSharp.Editor/BraceMatchingService.fs | 2 +- .../BreakpointResolutionService.fs | 2 +- .../src/FSharp.Editor/ColorizationService.fs | 4 ++-- .../src/FSharp.Editor/CompletionProvider.fs | 4 ++-- .../DocumentDiagnosticAnalyzer.fs | 4 ++-- .../src/FSharp.Editor/GoToDefinitionService.fs | 18 ++++++++++-------- .../src/FSharp.Editor/LanguageService.fs | 5 ++++- .../FSharp.Editor/ProjectDiagnosticAnalyzer.fs | 2 +- 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/BraceMatchingService.fs b/vsintegration/src/FSharp.Editor/BraceMatchingService.fs index c76b640b565..10b4d0c0cc8 100644 --- a/vsintegration/src/FSharp.Editor/BraceMatchingService.fs +++ b/vsintegration/src/FSharp.Editor/BraceMatchingService.fs @@ -15,7 +15,7 @@ type internal FSharpBraceMatchingService() = let isPositionInRange(range) = let span = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range) span.Start <= position && position < span.End - let! matchedBraces = FSharpChecker.Instance.MatchBracesAlternate(fileName, sourceText.ToString(), options) + let! matchedBraces = FSharpLanguageService.Checker.MatchBracesAlternate(fileName, sourceText.ToString(), options) return matchedBraces |> Seq.tryFind(fun(left, right) -> isPositionInRange(left) || isPositionInRange(right)) } diff --git a/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs b/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs index c50ae6cba46..b776d03d724 100644 --- a/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs +++ b/vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs @@ -32,7 +32,7 @@ open Microsoft.FSharp.Compiler.Range type internal FSharpBreakpointResolutionService() = static member GetBreakpointLocation(sourceText: SourceText, fileName: string, textSpan: TextSpan, options: FSharpProjectOptions) = async { - let! parseResults = FSharpChecker.Instance.ParseFileInProject(fileName, sourceText.ToString(), options) + let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(fileName, sourceText.ToString(), options) let textLine = sourceText.Lines.GetLineFromPosition(textSpan.Start) let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based diff --git a/vsintegration/src/FSharp.Editor/ColorizationService.fs b/vsintegration/src/FSharp.Editor/ColorizationService.fs index 1ab24a9d0a0..e4ae973b2ee 100644 --- a/vsintegration/src/FSharp.Editor/ColorizationService.fs +++ b/vsintegration/src/FSharp.Editor/ColorizationService.fs @@ -149,9 +149,9 @@ type internal FSharpColorizationService() = match FSharpLanguageService.GetOptions(document.Project.Id) with | Some(options) -> let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask - let! parseResults = FSharpChecker.Instance.ParseFileInProject(document.Name, sourceText.ToString(), options) + let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(document.Name, sourceText.ToString(), options) let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask - let! checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, document.FilePath, textVersion.GetHashCode(), textSpan.ToString(), options) + let! checkResultsAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, document.FilePath, textVersion.GetHashCode(), textSpan.ToString(), options) let extraColorizationData = match checkResultsAnswer with | FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet" diff --git a/vsintegration/src/FSharp.Editor/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/CompletionProvider.fs index 3c5c8878b34..f403fbc3731 100644 --- a/vsintegration/src/FSharp.Editor/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/CompletionProvider.fs @@ -73,8 +73,8 @@ type internal FSharpCompletionProvider(workspace: Workspace, serviceProvider: SV | _ -> true // anything else is a valid classification type static member ProvideCompletionsAsyncAux(sourceText: SourceText, caretPosition: int, options: FSharpProjectOptions, filePath: string, textVersionHash: int) = async { - let! parseResults = FSharpChecker.Instance.ParseFileInProject(filePath, sourceText.ToString(), options) - let! checkFileAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) + let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(filePath, sourceText.ToString(), options) + let! checkFileAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) let checkFileResults = match checkFileAnswer with | FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet" | FSharpCheckFileAnswer.Succeeded(results) -> results diff --git a/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs index 6eeb31ef073..c599df57638 100644 --- a/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs @@ -25,10 +25,10 @@ type internal FSharpDocumentDiagnosticAnalyzer() = inherit DocumentDiagnosticAnalyzer() static member GetDiagnostics(filePath: string, sourceText: SourceText, textVersionHash: int, options: FSharpProjectOptions, addSemanticErrors: bool) = - let parseResults = FSharpChecker.Instance.ParseFileInProject(filePath, sourceText.ToString(), options) |> Async.RunSynchronously + let parseResults = FSharpLanguageService.Checker.ParseFileInProject(filePath, sourceText.ToString(), options) |> Async.RunSynchronously let errors = if addSemanticErrors then - let checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) |> Async.RunSynchronously + let checkResultsAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) |> Async.RunSynchronously match checkResultsAnswer with | FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet" | FSharpCheckFileAnswer.Succeeded(results) -> results.Errors diff --git a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs index 62bc7bfd47b..6f36dc672fd 100644 --- a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs @@ -61,8 +61,8 @@ type internal FSharpGoToDefinitionService [] ([ Seq.tryFind(fun classifiedSpan -> classifiedSpan.TextSpan.Contains(position)) let processQualifiedIdentifier(qualifiers, islandColumn) = async { - let! parseResults = FSharpChecker.Instance.ParseFileInProject(filePath, sourceText.ToString(), options) - let! checkFileAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) + let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(filePath, sourceText.ToString(), options) + let! checkFileAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) let checkFileResults = match checkFileAnswer with | FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet" | FSharpCheckFileAnswer.Succeeded(results) -> results @@ -103,12 +103,14 @@ type internal FSharpGoToDefinitionService [] ([ - let refDocumentId = document.Project.Solution.GetDocumentIdsWithFilePath(range.FileName).First() - let refDocument = document.Project.Solution.GetDocument(refDocumentId) - let! refSourceText = refDocument.GetTextAsync(cancellationToken) |> Async.AwaitTask - let refTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan(refSourceText, range) - let refDisplayString = refSourceText.GetSubText(refTextSpan).ToString() - results.Add(FSharpNavigableItem(refDocument, refTextSpan, refDisplayString)) + let refDocumentIds = document.Project.Solution.GetDocumentIdsWithFilePath(range.FileName) + if not refDocumentIds.IsEmpty then + let refDocumentId = refDocumentIds.First() + let refDocument = document.Project.Solution.GetDocument(refDocumentId) + let! refSourceText = refDocument.GetTextAsync(cancellationToken) |> Async.AwaitTask + let refTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan(refSourceText, range) + let refDisplayString = refSourceText.GetSubText(refTextSpan).ToString() + results.Add(FSharpNavigableItem(refDocument, refTextSpan, refDisplayString)) | None -> () | None -> () return results.AsEnumerable() diff --git a/vsintegration/src/FSharp.Editor/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService.fs index ce73f66b85e..aa1aac86c12 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService.fs @@ -49,6 +49,9 @@ type internal FSharpLanguageService(package : FSharpPackage) = inherit AbstractLanguageService(package) static let optionsCache = Dictionary() + static let checker = lazy FSharpChecker.Create() + static member Checker with get() = checker.Value + static member GetOptions(projectId: ProjectId) = if optionsCache.ContainsKey(projectId) then Some(optionsCache.[projectId]) @@ -118,7 +121,7 @@ type internal FSharpLanguageService(package : FSharpPackage) = | _ -> () member this.SetupStandAloneFile(fileName: string, fileContents: string, workspace: VisualStudioWorkspaceImpl, hier: IVsHierarchy) = - let options = FSharpChecker.Instance.GetProjectOptionsFromScript(fileName, fileContents, DateTime.Now, [| |]) |> Async.RunSynchronously + let options = FSharpLanguageService.Checker.GetProjectOptionsFromScript(fileName, fileContents, DateTime.Now, [| |]) |> Async.RunSynchronously let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(options.ProjectFileName, options.ProjectFileName) if not(optionsCache.ContainsKey(projectId)) then diff --git a/vsintegration/src/FSharp.Editor/ProjectDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/ProjectDiagnosticAnalyzer.fs index df1e56d07a7..f80b6944b36 100644 --- a/vsintegration/src/FSharp.Editor/ProjectDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/ProjectDiagnosticAnalyzer.fs @@ -26,7 +26,7 @@ type internal FSharpProjectDiagnosticAnalyzer() = inherit ProjectDiagnosticAnalyzer() static member GetDiagnostics(options: FSharpProjectOptions) = - let checkProjectResults = FSharpChecker.Instance.ParseAndCheckProject(options) |> Async.RunSynchronously + let checkProjectResults = FSharpLanguageService.Checker.ParseAndCheckProject(options) |> Async.RunSynchronously (checkProjectResults.Errors |> Seq.choose(fun (error) -> if error.StartLineAlternate = 0 || error.EndLineAlternate = 0 then Some(CommonRoslynHelpers.ConvertError(error, Location.None))