提交 c4a8ff2e 编写于 作者: D Don Syme 提交者: Kevin Ransom (msft)

fix span bug (#3181)

上级 684e628e
......@@ -45,8 +45,11 @@ type internal FSharpColorizationService
let colorizationData = checkResults.GetSemanticClassification (Some targetRange) |> Array.distinctBy fst
for (range, classificationType) in colorizationData do
let span = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
result.Add(ClassifiedSpan(span, FSharpClassificationTypes.getClassificationTypeName(classificationType)))
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) with
| None -> ()
| Some span ->
let span = Tokenizer.fixupSpan(sourceText, span)
result.Add(ClassifiedSpan(span, FSharpClassificationTypes.getClassificationTypeName(classificationType)))
}
|> Async.Ignore |> RoslynHelpers.StartAsyncUnitAsTask cancellationToken
......
......@@ -21,8 +21,8 @@ module internal RoslynHelpers =
let FSharpRangeToTextSpan(sourceText: SourceText, range: range) =
// Roslyn TextLineCollection is zero-based, F# range lines are one-based
let startPosition = sourceText.Lines.[range.StartLine - 1].Start + range.StartColumn
let endPosition = sourceText.Lines.[range.EndLine - 1].Start + range.EndColumn
let startPosition = sourceText.Lines.[max 0 (range.StartLine - 1)].Start + range.StartColumn
let endPosition = sourceText.Lines.[min (range.EndLine - 1) (sourceText.Lines.Count - 1)].Start + range.EndColumn
TextSpan(startPosition, endPosition - startPosition)
let TryFSharpRangeToTextSpan(sourceText: SourceText, range: range) : TextSpan option =
......
......@@ -52,7 +52,8 @@ type internal FSharpBreakpointResolutionService
let! options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document)
let! sourceText = document.GetTextAsync(cancellationToken)
let! range = FSharpBreakpointResolutionService.GetBreakpointLocation(checkerProvider.Checker, sourceText, document.Name, textSpan, options)
return BreakpointResolutionResult.CreateSpanResult(document, RoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
let! span = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range)
return BreakpointResolutionResult.CreateSpanResult(document, span)
}
|> Async.map Option.toObj
|> RoslynHelpers.StartAsyncAsTask cancellationToken
......
......@@ -64,8 +64,11 @@ type internal FSharpDocumentHighlightsService [<ImportingConstructor>] (checkerP
let! symbolUses = checkFileResults.GetUsesOfSymbolInFile(symbolUse.Symbol) |> liftAsync
return
[| for symbolUse in symbolUses do
yield { IsDefinition = symbolUse.IsFromDefinition
TextSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) } |]
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) with
| None -> ()
| Some span ->
yield { IsDefinition = symbolUse.IsFromDefinition
TextSpan = span } |]
|> fixInvalidSymbolSpans sourceText symbol.Ident.idText
}
......
......@@ -19,7 +19,10 @@ type internal FSharpBraceMatchingService
static member GetBraceMatchingResult(checker: FSharpChecker, sourceText, fileName, options, position: int) =
async {
let! matchedBraces = checker.MatchBraces(fileName, sourceText.ToString(), options, userOpName = userOpName)
let isPositionInRange range = RoslynHelpers.FSharpRangeToTextSpan(sourceText, range).Contains(position)
let isPositionInRange range =
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) with
| None -> false
| Some range -> range.Contains(position)
return matchedBraces |> Array.tryFind(fun (left, right) -> isPositionInRange left || isPositionInRange right)
}
......@@ -29,10 +32,9 @@ type internal FSharpBraceMatchingService
let! options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document)
let! sourceText = document.GetTextAsync(cancellationToken)
let! (left, right) = FSharpBraceMatchingService.GetBraceMatchingResult(checkerProvider.Checker, sourceText, document.Name, options, position)
return
BraceMatchingResult(
RoslynHelpers.FSharpRangeToTextSpan(sourceText, left),
RoslynHelpers.FSharpRangeToTextSpan(sourceText, right))
let! leftSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, left)
let! rightSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, right)
return BraceMatchingResult(leftSpan, rightSpan)
}
|> Async.map Option.toNullable
|> RoslynHelpers.StartAsyncAsTask cancellationToken
......@@ -75,7 +75,7 @@ type internal InlineRenameInfo
checker: FSharpChecker,
projectInfoManager: ProjectInfoManager,
document: Document,
sourceText: SourceText,
triggerSpan: TextSpan,
lexerSymbol: LexerSymbol,
symbolUse: FSharpSymbolUse,
declLoc: SymbolDeclarationLocation,
......@@ -89,10 +89,6 @@ type internal InlineRenameInfo
| true, text -> text
| _ -> document.GetTextAsync(cancellationToken).Result
let triggerSpan =
let span = RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate)
Tokenizer.fixupSpan(sourceText, span)
let symbolUses =
SymbolHelpers.getSymbolUsesInSolution(symbolUse.Symbol, declLoc, checkFileResults, projectInfoManager, checker, document.Project.Solution, userOpName)
|> Async.cache
......@@ -126,9 +122,12 @@ type internal InlineRenameInfo
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let locations =
symbolUses
|> Array.map (fun symbolUse ->
let textSpan = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
InlineRenameLocation(document, textSpan))
|> Array.choose (fun symbolUse ->
RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate)
|> Option.map (fun span ->
let textSpan = Tokenizer.fixupSpan(sourceText, span)
InlineRenameLocation(document, textSpan)))
return { Document = document; Locations = locations }
})
|> Async.Parallel
......@@ -158,7 +157,11 @@ type internal InlineRenameService
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, allowStaleResults = true, userOpName = userOpName)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.Text.ToString(), symbol.FullIsland, userOpName=userOpName)
let! declLoc = symbolUse.GetDeclarationLocation(document)
return InlineRenameInfo(checker, projectInfoManager, document, sourceText, symbol, symbolUse, declLoc, checkFileResults) :> IInlineRenameInfo
let! span = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate)
let triggerSpan = Tokenizer.fixupSpan(sourceText, span)
return InlineRenameInfo(checker, projectInfoManager, document, triggerSpan, symbol, symbolUse, declLoc, checkFileResults) :> IInlineRenameInfo
}
interface IEditorInlineRenameService with
......
......@@ -95,9 +95,12 @@ module internal SymbolHelpers =
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let mutable sourceText = sourceText
for symbolUse in symbolUses do
let textSpan = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
sourceText <- sourceText.Replace(textSpan, newText)
solution <- solution.WithDocumentText(documentId, sourceText)
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) with
| None -> ()
| Some span ->
let textSpan = Tokenizer.fixupSpan(sourceText, span)
sourceText <- sourceText.Replace(textSpan, newText)
solution <- solution.WithDocumentText(documentId, sourceText)
return solution
} |> RoslynHelpers.StartAsyncAsTask cancellationToken),
originalText
......
......@@ -49,8 +49,9 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: Project
let refDocument = document.Project.Solution.GetDocument refDocumentId
let! cancellationToken = Async.CancellationToken
let! refSourceText = refDocument.GetTextAsync(cancellationToken) |> Async.AwaitTask
let refTextSpan = RoslynHelpers.FSharpRangeToTextSpan (refSourceText, range)
return Some (FSharpNavigableItem (refDocument, refTextSpan))
match RoslynHelpers.TryFSharpRangeToTextSpan (refSourceText, range) with
| None -> return None
| Some refTextSpan -> return Some (FSharpNavigableItem (refDocument, refTextSpan))
else return None
}
......@@ -59,7 +60,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: Project
asyncMaybe {
let! projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject originDocument
let defines = CompilerEnvironment.GetCompilationDefinesForEditing (originDocument.FilePath, projectOptions.OtherOptions |> Seq.toList)
let originTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sourceText, originRange)
let! originTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sourceText, originRange)
let position = originTextSpan.Start
let! lexerSymbol = Tokenizer.getSymbolAtPosition (originDocument.Id, sourceText, position, originDocument.FilePath, defines, SymbolLookupKind.Greedy, false)
......@@ -83,7 +84,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: Project
let! _, _, checkFileResults = checker.ParseAndCheckDocument (implDoc, projectOptions, allowStaleResults=true, sourceText=implSourceText, userOpName = userOpName)
let! symbolUses = checkFileResults.GetUsesOfSymbolInFile symbol |> liftAsync
let! implSymbol = symbolUses |> Array.tryHead
let implTextSpan = RoslynHelpers.FSharpRangeToTextSpan (implSourceText, implSymbol.RangeAlternate)
let! implTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (implSourceText, implSymbol.RangeAlternate)
return FSharpNavigableItem (implDoc, implTextSpan)
else
let! targetDocument = originDocument.Project.Solution.TryGetDocumentFromFSharpRange fsSymbolUse.RangeAlternate
......@@ -241,7 +242,7 @@ type internal FSharpGoToDefinitionService
let! targetRange =
gotoDefinition.FindSymbolDeclarationInFile(targetSymbolUse, implFilePath, implSourceText.ToString(), projectOptions, implVersion.GetHashCode())
let implTextSpan = RoslynHelpers.FSharpRangeToTextSpan (implSourceText, targetRange)
let! implTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (implSourceText, targetRange)
let navItem = FSharpNavigableItem (implDocument, implTextSpan)
return navItem
else // jump from implementation to the corresponding signature
......@@ -250,7 +251,7 @@ type internal FSharpGoToDefinitionService
| FSharpFindDeclResult.DeclFound targetRange ->
let! sigDocument = originDocument.Project.Solution.TryGetDocumentFromPath targetRange.FileName
let! sigSourceText = sigDocument.GetTextAsync () |> liftTaskAsync
let sigTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sigSourceText, targetRange)
let! sigTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sigSourceText, targetRange)
let navItem = FSharpNavigableItem (sigDocument, sigTextSpan)
return navItem
| _ -> return! None
......@@ -260,7 +261,7 @@ type internal FSharpGoToDefinitionService
else
let! sigDocument = originDocument.Project.Solution.TryGetDocumentFromPath targetRange.FileName
let! sigSourceText = sigDocument.GetTextAsync () |> liftTaskAsync
let sigTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sigSourceText, targetRange)
let! sigTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sigSourceText, targetRange)
// if the gotodef call originated from a signature and the returned target is a signature, navigate there
if isSignatureFile targetRange.FileName && preferSignature then
let navItem = FSharpNavigableItem (sigDocument, sigTextSpan)
......@@ -280,7 +281,7 @@ type internal FSharpGoToDefinitionService
let! targetRange =
gotoDefinition.FindSymbolDeclarationInFile(targetSymbolUse, implFilePath, implSourceText.ToString(), projectOptions, implVersion.GetHashCode())
let implTextSpan = RoslynHelpers.FSharpRangeToTextSpan (implSourceText, targetRange)
let! implTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (implSourceText, targetRange)
let navItem = FSharpNavigableItem (implDocument, implTextSpan)
return navItem
| _ -> return! None
......
......@@ -196,11 +196,13 @@ type internal FSharpNavigateToSearchService
match parseResults.ParseTree |> Option.map NavigateTo.getNavigableItems with
| Some items ->
[| for item in items do
let sourceSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, item.Range)
let glyph = Utils.navigateToItemKindToGlyph item.Kind
let kind = Utils.navigateToItemKindToRoslynKind item.Kind
let additionalInfo = Utils.containerToString item.Container document.Project
yield NavigableItem(document, sourceSpan, glyph, item.Name, kind, additionalInfo) |]
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, item.Range) with
| None -> ()
| Some sourceSpan ->
let glyph = Utils.navigateToItemKindToGlyph item.Kind
let kind = Utils.navigateToItemKindToRoslynKind item.Kind
let additionalInfo = Utils.containerToString item.Container document.Project
yield NavigableItem(document, sourceSpan, glyph, item.Name, kind, additionalInfo) |]
| None -> [||]
}
......
......@@ -50,7 +50,7 @@ module private FSharpQuickInfo =
let! extDocId = solution.GetDocumentIdsWithFilePath declRange.FileName |> Seq.tryHead
let extDocument = solution.GetProject(extDocId.ProjectId).GetDocument extDocId
let! extSourceText = extDocument.GetTextAsync cancellationToken
let extSpan = RoslynHelpers.FSharpRangeToTextSpan (extSourceText, declRange)
let! extSpan = RoslynHelpers.TryFSharpRangeToTextSpan (extSourceText, declRange)
let extLineText = (extSourceText.Lines.GetLineFromPosition extSpan.Start).ToString()
// project options need to be retrieved because the signature file could be in another project
......@@ -69,9 +69,10 @@ module private FSharpQuickInfo =
| extTooltipText ->
let! extSymbolUse =
extCheckFileResults.GetSymbolUseAtLocation(declRange.StartLine, extLexerSymbol.Ident.idRange.EndColumn, extLineText, extLexerSymbol.FullIsland, userOpName=userOpName)
let! span = RoslynHelpers.TryFSharpRangeToTextSpan (extSourceText, extLexerSymbol.Range)
return { StructuredText = extTooltipText
Span = RoslynHelpers.FSharpRangeToTextSpan (extSourceText, extLexerSymbol.Range)
Span = span
Symbol = extSymbolUse.Symbol
SymbolKind = extLexerSymbol.Kind }
}
......@@ -110,7 +111,7 @@ module private FSharpQuickInfo =
| FSharpToolTipText []
| FSharpToolTipText [FSharpStructuredToolTipElement.None] -> return! None
| _ ->
let targetTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sourceText, lexerSymbol.Range)
let! targetTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sourceText, lexerSymbol.Range)
return { StructuredText = targetTooltip
Span = targetTextSpan
Symbol = symbolUse.Symbol
......@@ -180,7 +181,8 @@ type internal FSharpQuickInfoProvider
| FSharpToolTipText [FSharpStructuredToolTipElement.None] -> return! None
| _ ->
let! symbolUse = checkFileResults.GetSymbolUseAtLocation (textLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland, userOpName=FSharpQuickInfo.userOpName)
return res, RoslynHelpers.FSharpRangeToTextSpan (sourceText, symbol.Range), symbolUse.Symbol, symbol.Kind
let! symbolSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sourceText, symbol.Range)
return res, symbolSpan, symbolUse.Symbol, symbol.Kind
}
interface IQuickInfoProvider with
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册